Merge remote-tracking branch 'upstream/master' into rustup
This commit is contained in:
commit
26321b35c8
40 changed files with 492 additions and 318 deletions
|
@ -2772,6 +2772,7 @@ Released 2018-09-13
|
||||||
[`same_item_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push
|
[`same_item_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push
|
||||||
[`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some
|
[`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some
|
||||||
[`self_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_assignment
|
[`self_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_assignment
|
||||||
|
[`self_named_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructor
|
||||||
[`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
|
[`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
|
||||||
[`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
|
[`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
|
||||||
[`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
|
[`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::snippet_opt;
|
||||||
use clippy_utils::ty::implements_trait;
|
use clippy_utils::ty::implements_trait;
|
||||||
use clippy_utils::{eq_expr_value, get_trait_def_id, trait_ref_of_method};
|
use clippy_utils::{binop_traits, sugg};
|
||||||
use clippy_utils::{higher, paths, sugg};
|
use clippy_utils::{eq_expr_value, trait_ref_of_method};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -85,71 +85,34 @@ impl<'tcx> LateLintPass<'tcx> for AssignOps {
|
||||||
let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| {
|
let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| {
|
||||||
let ty = cx.typeck_results().expr_ty(assignee);
|
let ty = cx.typeck_results().expr_ty(assignee);
|
||||||
let rty = cx.typeck_results().expr_ty(rhs);
|
let rty = cx.typeck_results().expr_ty(rhs);
|
||||||
macro_rules! ops {
|
if_chain! {
|
||||||
($op:expr,
|
if let Some((_, lang_item)) = binop_traits(op.node);
|
||||||
$cx:expr,
|
if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item);
|
||||||
$ty:expr,
|
let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id);
|
||||||
$rty:expr,
|
if trait_ref_of_method(cx, parent_fn)
|
||||||
$($trait_name:ident),+) => {
|
.map_or(true, |t| t.path.res.def_id() != trait_id);
|
||||||
match $op {
|
if implements_trait(cx, ty, trait_id, &[rty.into()]);
|
||||||
$(hir::BinOpKind::$trait_name => {
|
then {
|
||||||
let [krate, module] = paths::OPS_MODULE;
|
span_lint_and_then(
|
||||||
let path: [&str; 3] = [krate, module, concat!(stringify!($trait_name), "Assign")];
|
cx,
|
||||||
let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
|
ASSIGN_OP_PATTERN,
|
||||||
trait_id
|
expr.span,
|
||||||
} else {
|
"manual implementation of an assign operation",
|
||||||
return; // useless if the trait doesn't exist
|
|diag| {
|
||||||
};
|
if let (Some(snip_a), Some(snip_r)) =
|
||||||
// check that we are not inside an `impl AssignOp` of this exact operation
|
(snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
|
||||||
let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id);
|
{
|
||||||
if_chain! {
|
diag.span_suggestion(
|
||||||
if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
|
expr.span,
|
||||||
if trait_ref.path.res.def_id() == trait_id;
|
"replace it with",
|
||||||
then { return; }
|
format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
implements_trait($cx, $ty, trait_id, &[$rty])
|
},
|
||||||
},)*
|
);
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ops!(
|
|
||||||
op.node,
|
|
||||||
cx,
|
|
||||||
ty,
|
|
||||||
rty.into(),
|
|
||||||
Add,
|
|
||||||
Sub,
|
|
||||||
Mul,
|
|
||||||
Div,
|
|
||||||
Rem,
|
|
||||||
And,
|
|
||||||
Or,
|
|
||||||
BitAnd,
|
|
||||||
BitOr,
|
|
||||||
BitXor,
|
|
||||||
Shr,
|
|
||||||
Shl
|
|
||||||
) {
|
|
||||||
span_lint_and_then(
|
|
||||||
cx,
|
|
||||||
ASSIGN_OP_PATTERN,
|
|
||||||
expr.span,
|
|
||||||
"manual implementation of an assign operation",
|
|
||||||
|diag| {
|
|
||||||
if let (Some(snip_a), Some(snip_r)) =
|
|
||||||
(snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
|
|
||||||
{
|
|
||||||
diag.span_suggestion(
|
|
||||||
expr.span,
|
|
||||||
"replace it with",
|
|
||||||
format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut visitor = ExprVisitor {
|
let mut visitor = ExprVisitor {
|
||||||
|
@ -206,7 +169,7 @@ fn lint_misrefactored_assign_op(
|
||||||
if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) {
|
if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) {
|
||||||
let a = &sugg::Sugg::hir(cx, assignee, "..");
|
let a = &sugg::Sugg::hir(cx, assignee, "..");
|
||||||
let r = &sugg::Sugg::hir(cx, rhs, "..");
|
let r = &sugg::Sugg::hir(cx, rhs, "..");
|
||||||
let long = format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r));
|
let long = format!("{} = {}", snip_a, sugg::make_binop(op.node.into(), a, r));
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
expr.span,
|
expr.span,
|
||||||
&format!(
|
&format!(
|
||||||
|
|
|
@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
|
||||||
if macro_with_not_op(&left.kind) || macro_with_not_op(&right.kind) {
|
if macro_with_not_op(&left.kind) || macro_with_not_op(&right.kind) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if is_useless_with_eq_exprs(higher::binop(op.node)) && eq_expr_value(cx, left, right) {
|
if is_useless_with_eq_exprs(op.node.into()) && eq_expr_value(cx, left, right) {
|
||||||
span_lint(
|
span_lint(
|
||||||
cx,
|
cx,
|
||||||
EQ_OP,
|
EQ_OP,
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#![cfg_attr(bootstrap, allow(rustc::default_hash_types))]
|
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
|
|
@ -330,6 +330,7 @@ mod regex;
|
||||||
mod repeat_once;
|
mod repeat_once;
|
||||||
mod returns;
|
mod returns;
|
||||||
mod self_assignment;
|
mod self_assignment;
|
||||||
|
mod self_named_constructor;
|
||||||
mod semicolon_if_nothing_returned;
|
mod semicolon_if_nothing_returned;
|
||||||
mod serde_api;
|
mod serde_api;
|
||||||
mod shadow;
|
mod shadow;
|
||||||
|
@ -900,6 +901,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||||
returns::LET_AND_RETURN,
|
returns::LET_AND_RETURN,
|
||||||
returns::NEEDLESS_RETURN,
|
returns::NEEDLESS_RETURN,
|
||||||
self_assignment::SELF_ASSIGNMENT,
|
self_assignment::SELF_ASSIGNMENT,
|
||||||
|
self_named_constructor::SELF_NAMED_CONSTRUCTOR,
|
||||||
semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED,
|
semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED,
|
||||||
serde_api::SERDE_API_MISUSE,
|
serde_api::SERDE_API_MISUSE,
|
||||||
shadow::SHADOW_REUSE,
|
shadow::SHADOW_REUSE,
|
||||||
|
@ -1406,6 +1408,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||||
LintId::of(returns::LET_AND_RETURN),
|
LintId::of(returns::LET_AND_RETURN),
|
||||||
LintId::of(returns::NEEDLESS_RETURN),
|
LintId::of(returns::NEEDLESS_RETURN),
|
||||||
LintId::of(self_assignment::SELF_ASSIGNMENT),
|
LintId::of(self_assignment::SELF_ASSIGNMENT),
|
||||||
|
LintId::of(self_named_constructor::SELF_NAMED_CONSTRUCTOR),
|
||||||
LintId::of(serde_api::SERDE_API_MISUSE),
|
LintId::of(serde_api::SERDE_API_MISUSE),
|
||||||
LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
|
LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
|
||||||
LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
|
LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
|
||||||
|
@ -1559,6 +1562,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||||
LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
|
LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
|
||||||
LintId::of(returns::LET_AND_RETURN),
|
LintId::of(returns::LET_AND_RETURN),
|
||||||
LintId::of(returns::NEEDLESS_RETURN),
|
LintId::of(returns::NEEDLESS_RETURN),
|
||||||
|
LintId::of(self_named_constructor::SELF_NAMED_CONSTRUCTOR),
|
||||||
LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
|
LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
|
||||||
LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
|
LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
|
||||||
LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME),
|
LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME),
|
||||||
|
@ -2101,6 +2105,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||||
let scripts = conf.allowed_scripts.clone();
|
let scripts = conf.allowed_scripts.clone();
|
||||||
store.register_early_pass(move || box disallowed_script_idents::DisallowedScriptIdents::new(&scripts));
|
store.register_early_pass(move || box disallowed_script_idents::DisallowedScriptIdents::new(&scripts));
|
||||||
store.register_late_pass(|| box strlen_on_c_strings::StrlenOnCStrings);
|
store.register_late_pass(|| box strlen_on_c_strings::StrlenOnCStrings);
|
||||||
|
store.register_late_pass(move || box self_named_constructor::SelfNamedConstructor);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
|
|
@ -204,11 +204,8 @@ struct MinifyingSugg<'a>(Sugg<'a>);
|
||||||
|
|
||||||
impl<'a> MinifyingSugg<'a> {
|
impl<'a> MinifyingSugg<'a> {
|
||||||
fn as_str(&self) -> &str {
|
fn as_str(&self) -> &str {
|
||||||
// HACK: Don't sync to Clippy! Required because something with the `or_patterns` feature
|
let (Sugg::NonParen(s) | Sugg::MaybeParen(s) | Sugg::BinOp(_, s)) = &self.0;
|
||||||
// changed and this would now require parentheses.
|
s.as_ref()
|
||||||
match &self.0 {
|
|
||||||
Sugg::NonParen(s) | Sugg::MaybeParen(s) | Sugg::BinOp(_, s) => s.as_ref(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_sugg(self) -> Sugg<'a> {
|
fn into_sugg(self) -> Sugg<'a> {
|
||||||
|
|
|
@ -721,7 +721,7 @@ fn check_single_match_single_pattern(
|
||||||
expr: &Expr<'_>,
|
expr: &Expr<'_>,
|
||||||
els: Option<&Expr<'_>>,
|
els: Option<&Expr<'_>>,
|
||||||
) {
|
) {
|
||||||
if is_wild(&arms[1].pat) {
|
if is_wild(arms[1].pat) {
|
||||||
report_single_match_single_pattern(cx, ex, arms, expr, els);
|
report_single_match_single_pattern(cx, ex, arms, expr, els);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1287,7 +1287,7 @@ fn find_matches_sugg(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr
|
||||||
if let Some((b1_arm, b0_arms)) = arms.split_last();
|
if let Some((b1_arm, b0_arms)) = arms.split_last();
|
||||||
if let Some(b0) = find_bool_lit(&b0_arms[0].body.kind, desugared);
|
if let Some(b0) = find_bool_lit(&b0_arms[0].body.kind, desugared);
|
||||||
if let Some(b1) = find_bool_lit(&b1_arm.body.kind, desugared);
|
if let Some(b1) = find_bool_lit(&b1_arm.body.kind, desugared);
|
||||||
if is_wild(&b1_arm.pat);
|
if is_wild(b1_arm.pat);
|
||||||
if b0 != b1;
|
if b0 != b1;
|
||||||
let if_guard = &b0_arms[0].guard;
|
let if_guard = &b0_arms[0].guard;
|
||||||
if if_guard.is_none() || b0_arms.len() == 1;
|
if if_guard.is_none() || b0_arms.len() == 1;
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
|
|
||||||
use clippy_utils::attrs::is_doc_hidden;
|
use clippy_utils::attrs::is_doc_hidden;
|
||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use rustc_ast::ast;
|
use if_chain::if_chain;
|
||||||
|
use rustc_ast::ast::{self, MetaItem, MetaItemKind};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
|
@ -55,6 +56,20 @@ impl MissingDoc {
|
||||||
*self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
|
*self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_include(meta: Option<MetaItem>) -> bool {
|
||||||
|
if_chain! {
|
||||||
|
if let Some(meta) = meta;
|
||||||
|
if let MetaItemKind::List(list) = meta.kind;
|
||||||
|
if let Some(meta) = list.get(0);
|
||||||
|
if let Some(name) = meta.ident();
|
||||||
|
then {
|
||||||
|
name.name == sym::include
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check_missing_docs_attrs(
|
fn check_missing_docs_attrs(
|
||||||
&self,
|
&self,
|
||||||
cx: &LateContext<'_>,
|
cx: &LateContext<'_>,
|
||||||
|
@ -80,7 +95,7 @@ impl MissingDoc {
|
||||||
|
|
||||||
let has_doc = attrs
|
let has_doc = attrs
|
||||||
.iter()
|
.iter()
|
||||||
.any(|a| a.doc_str().is_some());
|
.any(|a| a.doc_str().is_some() || Self::has_include(a.meta()));
|
||||||
if !has_doc {
|
if !has_doc {
|
||||||
span_lint(
|
span_lint(
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -87,10 +87,6 @@ impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> {
|
||||||
self.found = true;
|
self.found = true;
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
ExprKind::If(..) => {
|
|
||||||
self.found = true;
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
ExprKind::Path(_) => {
|
ExprKind::Path(_) => {
|
||||||
if let Some(adj) = self.cx.typeck_results().adjustments().get(expr.hir_id) {
|
if let Some(adj) = self.cx.typeck_results().adjustments().get(expr.hir_id) {
|
||||||
if adj
|
if adj
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||||
use rustc_ast::ast::{
|
use rustc_ast::ast::{
|
||||||
Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, FnKind, Item, ItemKind, Local, Pat,
|
Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, FnKind, Item, ItemKind, Local, Pat, PatKind,
|
||||||
PatKind,
|
|
||||||
};
|
};
|
||||||
use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor};
|
use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor};
|
||||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||||
|
|
|
@ -724,7 +724,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
|
||||||
BinaryOp(_, box (lhs, rhs)) | CheckedBinaryOp(_, box (lhs, rhs)) => {
|
BinaryOp(_, box (lhs, rhs)) | CheckedBinaryOp(_, box (lhs, rhs)) => {
|
||||||
visit_op(lhs);
|
visit_op(lhs);
|
||||||
visit_op(rhs);
|
visit_op(rhs);
|
||||||
}
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
91
clippy_lints/src/self_named_constructor.rs
Normal file
91
clippy_lints/src/self_named_constructor.rs
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
use clippy_utils::diagnostics::span_lint;
|
||||||
|
use clippy_utils::return_ty;
|
||||||
|
use clippy_utils::ty::{contains_adt_constructor, contains_ty};
|
||||||
|
use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind, Node};
|
||||||
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// **What it does:** Warns when constructors have the same name as their types.
|
||||||
|
///
|
||||||
|
/// **Why is this bad?** Repeating the name of the type is redundant.
|
||||||
|
///
|
||||||
|
/// **Known problems:** None.
|
||||||
|
///
|
||||||
|
/// **Example:**
|
||||||
|
///
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// struct Foo {}
|
||||||
|
///
|
||||||
|
/// impl Foo {
|
||||||
|
/// pub fn foo() -> Foo {
|
||||||
|
/// Foo {}
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// Use instead:
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// struct Foo {}
|
||||||
|
///
|
||||||
|
/// impl Foo {
|
||||||
|
/// pub fn new() -> Foo {
|
||||||
|
/// Foo {}
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub SELF_NAMED_CONSTRUCTOR,
|
||||||
|
style,
|
||||||
|
"method should not have the same name as the type it is implemented for"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_lint_pass!(SelfNamedConstructor => [SELF_NAMED_CONSTRUCTOR]);
|
||||||
|
|
||||||
|
impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructor {
|
||||||
|
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
|
||||||
|
match impl_item.kind {
|
||||||
|
ImplItemKind::Fn(ref sig, _) => {
|
||||||
|
if sig.decl.implicit_self.has_implicit_self() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => return,
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
|
||||||
|
let item = cx.tcx.hir().expect_item(parent);
|
||||||
|
let self_ty = cx.tcx.type_of(item.def_id);
|
||||||
|
let ret_ty = return_ty(cx, impl_item.hir_id());
|
||||||
|
|
||||||
|
// Do not check trait impls
|
||||||
|
if matches!(item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. })) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure method is constructor-like
|
||||||
|
if let Some(self_adt) = self_ty.ty_adt_def() {
|
||||||
|
if !contains_adt_constructor(ret_ty, self_adt) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if !contains_ty(ret_ty, self_ty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if_chain! {
|
||||||
|
if let Some(self_def) = self_ty.ty_adt_def();
|
||||||
|
if let Some(self_local_did) = self_def.did.as_local();
|
||||||
|
let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did);
|
||||||
|
if let Some(Node::Item(x)) = cx.tcx.hir().find(self_id);
|
||||||
|
let type_name = x.ident.name.as_str().to_lowercase();
|
||||||
|
if impl_item.ident.name.as_str() == type_name || impl_item.ident.name.as_str().replace("_", "") == type_name;
|
||||||
|
|
||||||
|
then {
|
||||||
|
span_lint(
|
||||||
|
cx,
|
||||||
|
SELF_NAMED_CONSTRUCTOR,
|
||||||
|
impl_item.span,
|
||||||
|
&format!("constructor `{}` has the same name as the type", impl_item.ident.name),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use clippy_utils::{get_trait_def_id, paths, trait_ref_of_method};
|
use clippy_utils::{binop_traits, trait_ref_of_method, BINOP_TRAITS, OP_ASSIGN_TRAITS};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
|
||||||
|
@ -55,135 +55,48 @@ declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
|
impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
|
||||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
|
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
|
||||||
if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind {
|
if_chain! {
|
||||||
match binop.node {
|
if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind;
|
||||||
hir::BinOpKind::Eq
|
if let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop.node);
|
||||||
| hir::BinOpKind::Lt
|
if let Ok(binop_trait_id) = cx.tcx.lang_items().require(binop_trait_lang);
|
||||||
| hir::BinOpKind::Le
|
if let Ok(op_assign_trait_id) = cx.tcx.lang_items().require(op_assign_trait_lang);
|
||||||
| hir::BinOpKind::Ne
|
|
||||||
| hir::BinOpKind::Ge
|
|
||||||
| hir::BinOpKind::Gt => return,
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for more than one binary operation in the implemented function
|
// Check for more than one binary operation in the implemented function
|
||||||
// Linting when multiple operations are involved can result in false positives
|
// Linting when multiple operations are involved can result in false positives
|
||||||
let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
|
let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
|
||||||
if_chain! {
|
if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get(parent_fn);
|
||||||
if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get(parent_fn);
|
if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind;
|
||||||
if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind;
|
let body = cx.tcx.hir().body(body_id);
|
||||||
then {
|
let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
|
||||||
let body = cx.tcx.hir().body(body_id);
|
if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
|
||||||
let mut visitor = BinaryExprVisitor { nb_binops: 0 };
|
let trait_id = trait_ref.path.res.def_id();
|
||||||
walk_expr(&mut visitor, &body.value);
|
if ![binop_trait_id, op_assign_trait_id].contains(&trait_id);
|
||||||
if visitor.nb_binops > 1 {
|
if let Some(&(_, lint)) = [
|
||||||
return;
|
(&BINOP_TRAITS, SUSPICIOUS_ARITHMETIC_IMPL),
|
||||||
}
|
(&OP_ASSIGN_TRAITS, SUSPICIOUS_OP_ASSIGN_IMPL),
|
||||||
}
|
]
|
||||||
}
|
.iter()
|
||||||
|
.find(|&(ts, _)| ts.iter().any(|&t| Ok(trait_id) == cx.tcx.lang_items().require(t)));
|
||||||
if let Some(impl_trait) = check_binop(
|
if count_binops(&body.value) == 1;
|
||||||
cx,
|
then {
|
||||||
expr,
|
|
||||||
binop.node,
|
|
||||||
&[
|
|
||||||
"Add", "Sub", "Mul", "Div", "Rem", "BitAnd", "BitOr", "BitXor", "Shl", "Shr",
|
|
||||||
],
|
|
||||||
&[
|
|
||||||
hir::BinOpKind::Add,
|
|
||||||
hir::BinOpKind::Sub,
|
|
||||||
hir::BinOpKind::Mul,
|
|
||||||
hir::BinOpKind::Div,
|
|
||||||
hir::BinOpKind::Rem,
|
|
||||||
hir::BinOpKind::BitAnd,
|
|
||||||
hir::BinOpKind::BitOr,
|
|
||||||
hir::BinOpKind::BitXor,
|
|
||||||
hir::BinOpKind::Shl,
|
|
||||||
hir::BinOpKind::Shr,
|
|
||||||
],
|
|
||||||
) {
|
|
||||||
span_lint(
|
span_lint(
|
||||||
cx,
|
cx,
|
||||||
SUSPICIOUS_ARITHMETIC_IMPL,
|
lint,
|
||||||
binop.span,
|
binop.span,
|
||||||
&format!("suspicious use of binary operator in `{}` impl", impl_trait),
|
&format!("suspicious use of `{}` in `{}` impl", binop.node.as_str(), cx.tcx.item_name(trait_id)),
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(impl_trait) = check_binop(
|
|
||||||
cx,
|
|
||||||
expr,
|
|
||||||
binop.node,
|
|
||||||
&[
|
|
||||||
"AddAssign",
|
|
||||||
"SubAssign",
|
|
||||||
"MulAssign",
|
|
||||||
"DivAssign",
|
|
||||||
"BitAndAssign",
|
|
||||||
"BitOrAssign",
|
|
||||||
"BitXorAssign",
|
|
||||||
"RemAssign",
|
|
||||||
"ShlAssign",
|
|
||||||
"ShrAssign",
|
|
||||||
],
|
|
||||||
&[
|
|
||||||
hir::BinOpKind::Add,
|
|
||||||
hir::BinOpKind::Sub,
|
|
||||||
hir::BinOpKind::Mul,
|
|
||||||
hir::BinOpKind::Div,
|
|
||||||
hir::BinOpKind::BitAnd,
|
|
||||||
hir::BinOpKind::BitOr,
|
|
||||||
hir::BinOpKind::BitXor,
|
|
||||||
hir::BinOpKind::Rem,
|
|
||||||
hir::BinOpKind::Shl,
|
|
||||||
hir::BinOpKind::Shr,
|
|
||||||
],
|
|
||||||
) {
|
|
||||||
span_lint(
|
|
||||||
cx,
|
|
||||||
SUSPICIOUS_OP_ASSIGN_IMPL,
|
|
||||||
binop.span,
|
|
||||||
&format!("suspicious use of binary operator in `{}` impl", impl_trait),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_binop(
|
fn count_binops(expr: &hir::Expr<'_>) -> u32 {
|
||||||
cx: &LateContext<'_>,
|
let mut visitor = BinaryExprVisitor::default();
|
||||||
expr: &hir::Expr<'_>,
|
visitor.visit_expr(expr);
|
||||||
binop: hir::BinOpKind,
|
visitor.nb_binops
|
||||||
traits: &[&'static str],
|
|
||||||
expected_ops: &[hir::BinOpKind],
|
|
||||||
) -> Option<&'static str> {
|
|
||||||
let mut trait_ids = vec![];
|
|
||||||
let [krate, module] = paths::OPS_MODULE;
|
|
||||||
|
|
||||||
for &t in traits {
|
|
||||||
let path = [krate, module, t];
|
|
||||||
if let Some(trait_id) = get_trait_def_id(cx, &path) {
|
|
||||||
trait_ids.push(trait_id);
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the actually implemented trait
|
|
||||||
let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
|
|
||||||
|
|
||||||
if_chain! {
|
|
||||||
if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
|
|
||||||
if let Some(idx) = trait_ids.iter().position(|&tid| tid == trait_ref.path.res.def_id());
|
|
||||||
if binop != expected_ops[idx];
|
|
||||||
then{
|
|
||||||
return Some(traits[idx])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
struct BinaryExprVisitor {
|
struct BinaryExprVisitor {
|
||||||
nb_binops: u32,
|
nb_binops: u32,
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item, match_type};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_hir::{self as hir, HirId, ItemKind, Node};
|
use rustc_hir::{self as hir, HirId, ItemKind, Node};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty::{Adt, Ty};
|
use rustc_middle::ty::{Adt, Ty, TypeFoldable};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
use rustc_target::abi::LayoutOf as _;
|
use rustc_target::abi::LayoutOf as _;
|
||||||
|
@ -52,6 +52,9 @@ impl LateLintPass<'_> for ZeroSizedMapValues {
|
||||||
if is_type_diagnostic_item(cx, ty, sym::hashmap_type) || match_type(cx, ty, &paths::BTREEMAP);
|
if is_type_diagnostic_item(cx, ty, sym::hashmap_type) || match_type(cx, ty, &paths::BTREEMAP);
|
||||||
if let Adt(_, substs) = ty.kind();
|
if let Adt(_, substs) = ty.kind();
|
||||||
let ty = substs.type_at(1);
|
let ty = substs.type_at(1);
|
||||||
|
// Fixes https://github.com/rust-lang/rust-clippy/issues/7447 because of
|
||||||
|
// https://github.com/rust-lang/rust/blob/master/compiler/rustc_middle/src/ty/sty.rs#L968
|
||||||
|
if !ty.has_escaping_bound_vars();
|
||||||
// Do this to prevent `layout_of` crashing, being unable to fully normalize `ty`.
|
// Do this to prevent `layout_of` crashing, being unable to fully normalize `ty`.
|
||||||
if is_normalizable(cx, cx.param_env, ty);
|
if is_normalizable(cx, cx.param_env, ty);
|
||||||
if let Ok(layout) = cx.layout_of(ty);
|
if let Ok(layout) = cx.layout_of(ty);
|
||||||
|
|
|
@ -11,31 +11,6 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, StmtKind, UnOp};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::{sym, ExpnKind, Span, Symbol};
|
use rustc_span::{sym, ExpnKind, Span, Symbol};
|
||||||
|
|
||||||
/// Converts a hir binary operator to the corresponding `ast` type.
|
|
||||||
#[must_use]
|
|
||||||
pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
|
|
||||||
match op {
|
|
||||||
hir::BinOpKind::Eq => ast::BinOpKind::Eq,
|
|
||||||
hir::BinOpKind::Ge => ast::BinOpKind::Ge,
|
|
||||||
hir::BinOpKind::Gt => ast::BinOpKind::Gt,
|
|
||||||
hir::BinOpKind::Le => ast::BinOpKind::Le,
|
|
||||||
hir::BinOpKind::Lt => ast::BinOpKind::Lt,
|
|
||||||
hir::BinOpKind::Ne => ast::BinOpKind::Ne,
|
|
||||||
hir::BinOpKind::Or => ast::BinOpKind::Or,
|
|
||||||
hir::BinOpKind::Add => ast::BinOpKind::Add,
|
|
||||||
hir::BinOpKind::And => ast::BinOpKind::And,
|
|
||||||
hir::BinOpKind::BitAnd => ast::BinOpKind::BitAnd,
|
|
||||||
hir::BinOpKind::BitOr => ast::BinOpKind::BitOr,
|
|
||||||
hir::BinOpKind::BitXor => ast::BinOpKind::BitXor,
|
|
||||||
hir::BinOpKind::Div => ast::BinOpKind::Div,
|
|
||||||
hir::BinOpKind::Mul => ast::BinOpKind::Mul,
|
|
||||||
hir::BinOpKind::Rem => ast::BinOpKind::Rem,
|
|
||||||
hir::BinOpKind::Shl => ast::BinOpKind::Shl,
|
|
||||||
hir::BinOpKind::Shr => ast::BinOpKind::Shr,
|
|
||||||
hir::BinOpKind::Sub => ast::BinOpKind::Sub,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represent a range akin to `ast::ExprKind::Range`.
|
/// Represent a range akin to `ast::ExprKind::Range`.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Range<'a> {
|
pub struct Range<'a> {
|
||||||
|
|
|
@ -909,12 +909,8 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool
|
||||||
if is_integer_literal(e, value) {
|
if is_integer_literal(e, value) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
let map = cx.tcx.hir();
|
let enclosing_body = cx.tcx.hir().local_def_id(cx.tcx.hir().enclosing_body_owner(e.hir_id));
|
||||||
let parent_item = map.get_parent_item(e.hir_id);
|
if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
|
||||||
if let Some((Constant::Int(v), _)) = map
|
|
||||||
.maybe_body_owned_by(parent_item)
|
|
||||||
.and_then(|body_id| constant(cx, cx.tcx.typeck_body(body_id), e))
|
|
||||||
{
|
|
||||||
value == v
|
value == v
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -1041,18 +1037,14 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
|
||||||
PatKind::Struct(ref qpath, fields, _) => {
|
PatKind::Struct(ref qpath, fields, _) => {
|
||||||
is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat))
|
is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat))
|
||||||
},
|
},
|
||||||
PatKind::TupleStruct(ref qpath, pats, _) => {
|
PatKind::TupleStruct(ref qpath, pats, _) => is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats),
|
||||||
is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats)
|
|
||||||
},
|
|
||||||
PatKind::Slice(head, middle, tail) => {
|
PatKind::Slice(head, middle, tail) => {
|
||||||
match &cx.typeck_results().node_type(pat.hir_id).kind() {
|
match &cx.typeck_results().node_type(pat.hir_id).kind() {
|
||||||
rustc_ty::Slice(..) => {
|
rustc_ty::Slice(..) => {
|
||||||
// [..] is the only irrefutable slice pattern.
|
// [..] is the only irrefutable slice pattern.
|
||||||
!head.is_empty() || middle.is_none() || !tail.is_empty()
|
!head.is_empty() || middle.is_none() || !tail.is_empty()
|
||||||
},
|
},
|
||||||
rustc_ty::Array(..) => {
|
rustc_ty::Array(..) => are_refutable(cx, head.iter().chain(middle).chain(tail.iter())),
|
||||||
are_refutable(cx, head.iter().chain(middle).chain(tail.iter()))
|
|
||||||
},
|
|
||||||
_ => {
|
_ => {
|
||||||
// unreachable!()
|
// unreachable!()
|
||||||
true
|
true
|
||||||
|
@ -1710,3 +1702,34 @@ pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool {
|
||||||
|
|
||||||
matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test")
|
matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! op_utils {
|
||||||
|
($($name:ident $assign:ident)*) => {
|
||||||
|
/// Binary operation traits like `LangItem::Add`
|
||||||
|
pub static BINOP_TRAITS: &[LangItem] = &[$(LangItem::$name,)*];
|
||||||
|
|
||||||
|
/// Operator-Assign traits like `LangItem::AddAssign`
|
||||||
|
pub static OP_ASSIGN_TRAITS: &[LangItem] = &[$(LangItem::$assign,)*];
|
||||||
|
|
||||||
|
/// Converts `BinOpKind::Add` to `(LangItem::Add, LangItem::AddAssign)`, for example
|
||||||
|
pub fn binop_traits(kind: hir::BinOpKind) -> Option<(LangItem, LangItem)> {
|
||||||
|
match kind {
|
||||||
|
$(hir::BinOpKind::$name => Some((LangItem::$name, LangItem::$assign)),)*
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
op_utils! {
|
||||||
|
Add AddAssign
|
||||||
|
Sub SubAssign
|
||||||
|
Mul MulAssign
|
||||||
|
Div DivAssign
|
||||||
|
Rem RemAssign
|
||||||
|
BitXor BitXorAssign
|
||||||
|
BitAnd BitAndAssign
|
||||||
|
BitOr BitOrAssign
|
||||||
|
Shl ShlAssign
|
||||||
|
Shr ShrAssign
|
||||||
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ impl<'a> Sugg<'a> {
|
||||||
| hir::ExprKind::Err => Sugg::NonParen(snippet),
|
| hir::ExprKind::Err => Sugg::NonParen(snippet),
|
||||||
hir::ExprKind::Assign(..) => Sugg::BinOp(AssocOp::Assign, snippet),
|
hir::ExprKind::Assign(..) => Sugg::BinOp(AssocOp::Assign, snippet),
|
||||||
hir::ExprKind::AssignOp(op, ..) => Sugg::BinOp(hirbinop2assignop(op), snippet),
|
hir::ExprKind::AssignOp(op, ..) => Sugg::BinOp(hirbinop2assignop(op), snippet),
|
||||||
hir::ExprKind::Binary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(higher::binop(op.node)), snippet),
|
hir::ExprKind::Binary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(op.node.into()), snippet),
|
||||||
hir::ExprKind::Cast(..) => Sugg::BinOp(AssocOp::As, snippet),
|
hir::ExprKind::Cast(..) => Sugg::BinOp(AssocOp::As, snippet),
|
||||||
hir::ExprKind::Type(..) => Sugg::BinOp(AssocOp::Colon, snippet),
|
hir::ExprKind::Type(..) => Sugg::BinOp(AssocOp::Colon, snippet),
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,10 +257,12 @@ pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the type is equal to a lang item
|
/// Checks if the type is equal to a lang item.
|
||||||
|
///
|
||||||
|
/// Returns `false` if the `LangItem` is not defined.
|
||||||
pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool {
|
pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool {
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
ty::Adt(adt, _) => cx.tcx.lang_items().require(lang_item).unwrap() == adt.did,
|
ty::Adt(adt, _) => cx.tcx.lang_items().require(lang_item).map_or(false, |li| li == adt.did),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ the codebase take a look at [Adding Lints] or [Common Tools].
|
||||||
- [lintcheck](#lintcheck)
|
- [lintcheck](#lintcheck)
|
||||||
- [PR](#pr)
|
- [PR](#pr)
|
||||||
- [Common Abbreviations](#common-abbreviations)
|
- [Common Abbreviations](#common-abbreviations)
|
||||||
|
- [Install from source](#install-from-source)
|
||||||
|
|
||||||
## Get the Code
|
## Get the Code
|
||||||
|
|
||||||
|
@ -128,4 +129,45 @@ This is a concise list of abbreviations that can come up during Clippy developme
|
||||||
general list can be found in the [rustc-dev-guide glossary][glossary]. Always feel free to ask if
|
general list can be found in the [rustc-dev-guide glossary][glossary]. Always feel free to ask if
|
||||||
an abbreviation or meaning is unclear to you.
|
an abbreviation or meaning is unclear to you.
|
||||||
|
|
||||||
|
## Install from source
|
||||||
|
|
||||||
|
If you are hacking on Clippy and want to install it from source, do the following:
|
||||||
|
|
||||||
|
First, take note of the toolchain [override](https://rust-lang.github.io/rustup/overrides.html) in `/rust-toolchain`.
|
||||||
|
We will use this override to install Clippy into the right toolchain.
|
||||||
|
|
||||||
|
> Tip: You can view the active toolchain for the current directory with `rustup show active-toolchain`.
|
||||||
|
|
||||||
|
From the Clippy project root, run the following command to build the Clippy binaries and copy them into the
|
||||||
|
toolchain directory. This will override the currently installed Clippy component.
|
||||||
|
|
||||||
|
```terminal
|
||||||
|
cargo build --release --bin cargo-clippy --bin clippy-driver -Zunstable-options --out-dir "$(rustc --print=sysroot)/bin"
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you may run `cargo clippy` in any project, using the toolchain where you just installed Clippy.
|
||||||
|
|
||||||
|
```terminal
|
||||||
|
cd my-project
|
||||||
|
cargo +nightly-2021-07-01 clippy
|
||||||
|
```
|
||||||
|
|
||||||
|
...or `clippy-driver`
|
||||||
|
|
||||||
|
```terminal
|
||||||
|
clippy-driver +nightly-2021-07-01 <filename>
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need to restore the default Clippy installation, run the following (from the Clippy project root).
|
||||||
|
|
||||||
|
```terminal
|
||||||
|
rustup component remove clippy
|
||||||
|
rustup component add clippy
|
||||||
|
```
|
||||||
|
|
||||||
|
> **DO NOT** install using `cargo install --path . --force` since this will overwrite rustup
|
||||||
|
[proxies](https://rust-lang.github.io/rustup/concepts/proxies.html). That is, `~/.cargo/bin/cargo-clippy` and
|
||||||
|
`~/.cargo/bin/clippy-driver` should be hard or soft links to `~/.cargo/bin/rustup`. You can repair these by running
|
||||||
|
`rustup update`.
|
||||||
|
|
||||||
[glossary]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html
|
[glossary]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
struct Foo {}
|
struct Foo {}
|
||||||
|
|
||||||
impl Foo {
|
impl Foo {
|
||||||
fn foo() -> Self {
|
fn new() -> Self {
|
||||||
impl Foo {
|
impl Foo {
|
||||||
fn bar() {}
|
fn bar() {}
|
||||||
}
|
}
|
||||||
|
|
6
tests/ui/crashes/ice-7340.rs
Normal file
6
tests/ui/crashes/ice-7340.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#![allow(clippy::no_effect)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
const CONSTANT: usize = 8;
|
||||||
|
[1; 1 % CONSTANT];
|
||||||
|
}
|
31
tests/ui/crashes/ice-7410.rs
Normal file
31
tests/ui/crashes/ice-7410.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// compile-flags: -Clink-arg=-nostartfiles
|
||||||
|
// ignore-macos
|
||||||
|
// ignore-windows
|
||||||
|
|
||||||
|
#![feature(lang_items, start, libc)]
|
||||||
|
#![no_std]
|
||||||
|
#![allow(clippy::redundant_pattern_matching)]
|
||||||
|
|
||||||
|
use core::panic::PanicInfo;
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl Drop for S {
|
||||||
|
fn drop(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[start]
|
||||||
|
fn main(argc: isize, argv: *const *const u8) -> isize {
|
||||||
|
if let Some(_) = Some(S) {
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
fn panic(_info: &PanicInfo) -> ! {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[lang = "eh_personality"]
|
||||||
|
extern "C" fn eh_personality() {}
|
25
tests/ui/issue-7447.rs
Normal file
25
tests/ui/issue-7447.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
use std::{borrow::Cow, collections::BTreeMap, marker::PhantomData, sync::Arc};
|
||||||
|
|
||||||
|
fn byte_view<'a>(s: &'a ByteView<'_>) -> BTreeMap<&'a str, ByteView<'a>> {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn group_entries(s: &()) -> BTreeMap<Cow<'_, str>, Vec<Cow<'_, str>>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Mmap;
|
||||||
|
|
||||||
|
enum ByteViewBacking<'a> {
|
||||||
|
Buf(Cow<'a, [u8]>),
|
||||||
|
Mmap(Mmap),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ByteView<'a> {
|
||||||
|
backing: Arc<ByteViewBacking<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
byte_view(panic!());
|
||||||
|
group_entries(panic!());
|
||||||
|
}
|
|
@ -25,7 +25,9 @@ async fn all_to_one<'a>(a: &'a str, _b: &'a str) -> &'a str {
|
||||||
struct Foo;
|
struct Foo;
|
||||||
impl Foo {
|
impl Foo {
|
||||||
// ok
|
// ok
|
||||||
pub async fn foo(&mut self) {}
|
pub async fn new(&mut self) -> Self {
|
||||||
|
Foo {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rust-lang/rust#61115
|
// rust-lang/rust#61115
|
||||||
|
|
|
@ -59,7 +59,9 @@ pub trait E: Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Foo {
|
impl Foo {
|
||||||
pub fn foo() {}
|
pub fn new() -> Self {
|
||||||
|
Foo { a: 0, b: 0 }
|
||||||
|
}
|
||||||
fn bar() {}
|
fn bar() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,23 +78,25 @@ LL | type AssociatedTypeDef = Self;
|
||||||
error: missing documentation for an associated function
|
error: missing documentation for an associated function
|
||||||
--> $DIR/missing-doc-impl.rs:62:5
|
--> $DIR/missing-doc-impl.rs:62:5
|
||||||
|
|
|
|
||||||
LL | pub fn foo() {}
|
LL | / pub fn new() -> Self {
|
||||||
| ^^^^^^^^^^^^^^^
|
LL | | Foo { a: 0, b: 0 }
|
||||||
|
LL | | }
|
||||||
|
| |_____^
|
||||||
|
|
||||||
error: missing documentation for an associated function
|
error: missing documentation for an associated function
|
||||||
--> $DIR/missing-doc-impl.rs:63:5
|
--> $DIR/missing-doc-impl.rs:65:5
|
||||||
|
|
|
|
||||||
LL | fn bar() {}
|
LL | fn bar() {}
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: missing documentation for an associated function
|
error: missing documentation for an associated function
|
||||||
--> $DIR/missing-doc-impl.rs:67:5
|
--> $DIR/missing-doc-impl.rs:69:5
|
||||||
|
|
|
|
||||||
LL | pub fn foo() {}
|
LL | pub fn foo() {}
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: missing documentation for an associated function
|
error: missing documentation for an associated function
|
||||||
--> $DIR/missing-doc-impl.rs:71:5
|
--> $DIR/missing-doc-impl.rs:73:5
|
||||||
|
|
|
|
||||||
LL | / fn foo2() -> u32 {
|
LL | / fn foo2() -> u32 {
|
||||||
LL | | 1
|
LL | | 1
|
||||||
|
|
|
@ -84,7 +84,7 @@ mod with_drop {
|
||||||
|
|
||||||
impl A {
|
impl A {
|
||||||
// This can not be const because the type implements `Drop`.
|
// This can not be const because the type implements `Drop`.
|
||||||
pub fn a(self) -> B {
|
pub fn b(self) -> B {
|
||||||
B
|
B
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
dead_code,
|
dead_code,
|
||||||
clippy::no_effect,
|
clippy::no_effect,
|
||||||
clippy::if_same_then_else,
|
clippy::if_same_then_else,
|
||||||
clippy::needless_return
|
clippy::needless_return,
|
||||||
|
clippy::self_named_constructor
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
dead_code,
|
dead_code,
|
||||||
clippy::no_effect,
|
clippy::no_effect,
|
||||||
clippy::if_same_then_else,
|
clippy::if_same_then_else,
|
||||||
clippy::needless_return
|
clippy::needless_return,
|
||||||
|
clippy::self_named_constructor
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: this if-then-else expression returns a bool literal
|
error: this if-then-else expression returns a bool literal
|
||||||
--> $DIR/fixable.rs:39:5
|
--> $DIR/fixable.rs:40:5
|
||||||
|
|
|
|
||||||
LL | / if x {
|
LL | / if x {
|
||||||
LL | | true
|
LL | | true
|
||||||
|
@ -11,7 +11,7 @@ LL | | };
|
||||||
= note: `-D clippy::needless-bool` implied by `-D warnings`
|
= note: `-D clippy::needless-bool` implied by `-D warnings`
|
||||||
|
|
||||||
error: this if-then-else expression returns a bool literal
|
error: this if-then-else expression returns a bool literal
|
||||||
--> $DIR/fixable.rs:44:5
|
--> $DIR/fixable.rs:45:5
|
||||||
|
|
|
|
||||||
LL | / if x {
|
LL | / if x {
|
||||||
LL | | false
|
LL | | false
|
||||||
|
@ -21,7 +21,7 @@ LL | | };
|
||||||
| |_____^ help: you can reduce it to: `!x`
|
| |_____^ help: you can reduce it to: `!x`
|
||||||
|
|
||||||
error: this if-then-else expression returns a bool literal
|
error: this if-then-else expression returns a bool literal
|
||||||
--> $DIR/fixable.rs:49:5
|
--> $DIR/fixable.rs:50:5
|
||||||
|
|
|
|
||||||
LL | / if x && y {
|
LL | / if x && y {
|
||||||
LL | | false
|
LL | | false
|
||||||
|
@ -31,7 +31,7 @@ LL | | };
|
||||||
| |_____^ help: you can reduce it to: `!(x && y)`
|
| |_____^ help: you can reduce it to: `!(x && y)`
|
||||||
|
|
||||||
error: this if-then-else expression returns a bool literal
|
error: this if-then-else expression returns a bool literal
|
||||||
--> $DIR/fixable.rs:69:5
|
--> $DIR/fixable.rs:70:5
|
||||||
|
|
|
|
||||||
LL | / if x {
|
LL | / if x {
|
||||||
LL | | return true;
|
LL | | return true;
|
||||||
|
@ -41,7 +41,7 @@ LL | | };
|
||||||
| |_____^ help: you can reduce it to: `return x`
|
| |_____^ help: you can reduce it to: `return x`
|
||||||
|
|
||||||
error: this if-then-else expression returns a bool literal
|
error: this if-then-else expression returns a bool literal
|
||||||
--> $DIR/fixable.rs:77:5
|
--> $DIR/fixable.rs:78:5
|
||||||
|
|
|
|
||||||
LL | / if x {
|
LL | / if x {
|
||||||
LL | | return false;
|
LL | | return false;
|
||||||
|
@ -51,7 +51,7 @@ LL | | };
|
||||||
| |_____^ help: you can reduce it to: `return !x`
|
| |_____^ help: you can reduce it to: `return !x`
|
||||||
|
|
||||||
error: this if-then-else expression returns a bool literal
|
error: this if-then-else expression returns a bool literal
|
||||||
--> $DIR/fixable.rs:85:5
|
--> $DIR/fixable.rs:86:5
|
||||||
|
|
|
|
||||||
LL | / if x && y {
|
LL | / if x && y {
|
||||||
LL | | return true;
|
LL | | return true;
|
||||||
|
@ -61,7 +61,7 @@ LL | | };
|
||||||
| |_____^ help: you can reduce it to: `return x && y`
|
| |_____^ help: you can reduce it to: `return x && y`
|
||||||
|
|
||||||
error: this if-then-else expression returns a bool literal
|
error: this if-then-else expression returns a bool literal
|
||||||
--> $DIR/fixable.rs:93:5
|
--> $DIR/fixable.rs:94:5
|
||||||
|
|
|
|
||||||
LL | / if x && y {
|
LL | / if x && y {
|
||||||
LL | | return false;
|
LL | | return false;
|
||||||
|
@ -71,7 +71,7 @@ LL | | };
|
||||||
| |_____^ help: you can reduce it to: `return !(x && y)`
|
| |_____^ help: you can reduce it to: `return !(x && y)`
|
||||||
|
|
||||||
error: equality checks against true are unnecessary
|
error: equality checks against true are unnecessary
|
||||||
--> $DIR/fixable.rs:101:8
|
--> $DIR/fixable.rs:102:8
|
||||||
|
|
|
|
||||||
LL | if x == true {};
|
LL | if x == true {};
|
||||||
| ^^^^^^^^^ help: try simplifying it as shown: `x`
|
| ^^^^^^^^^ help: try simplifying it as shown: `x`
|
||||||
|
@ -79,25 +79,25 @@ LL | if x == true {};
|
||||||
= note: `-D clippy::bool-comparison` implied by `-D warnings`
|
= note: `-D clippy::bool-comparison` implied by `-D warnings`
|
||||||
|
|
||||||
error: equality checks against false can be replaced by a negation
|
error: equality checks against false can be replaced by a negation
|
||||||
--> $DIR/fixable.rs:105:8
|
--> $DIR/fixable.rs:106:8
|
||||||
|
|
|
|
||||||
LL | if x == false {};
|
LL | if x == false {};
|
||||||
| ^^^^^^^^^^ help: try simplifying it as shown: `!x`
|
| ^^^^^^^^^^ help: try simplifying it as shown: `!x`
|
||||||
|
|
||||||
error: equality checks against true are unnecessary
|
error: equality checks against true are unnecessary
|
||||||
--> $DIR/fixable.rs:115:8
|
--> $DIR/fixable.rs:116:8
|
||||||
|
|
|
|
||||||
LL | if x == true {};
|
LL | if x == true {};
|
||||||
| ^^^^^^^^^ help: try simplifying it as shown: `x`
|
| ^^^^^^^^^ help: try simplifying it as shown: `x`
|
||||||
|
|
||||||
error: equality checks against false can be replaced by a negation
|
error: equality checks against false can be replaced by a negation
|
||||||
--> $DIR/fixable.rs:116:8
|
--> $DIR/fixable.rs:117:8
|
||||||
|
|
|
|
||||||
LL | if x == false {};
|
LL | if x == false {};
|
||||||
| ^^^^^^^^^^ help: try simplifying it as shown: `!x`
|
| ^^^^^^^^^^ help: try simplifying it as shown: `!x`
|
||||||
|
|
||||||
error: this if-then-else expression returns a bool literal
|
error: this if-then-else expression returns a bool literal
|
||||||
--> $DIR/fixable.rs:125:12
|
--> $DIR/fixable.rs:126:12
|
||||||
|
|
|
|
||||||
LL | } else if returns_bool() {
|
LL | } else if returns_bool() {
|
||||||
| ____________^
|
| ____________^
|
||||||
|
|
59
tests/ui/self_named_constructor.rs
Normal file
59
tests/ui/self_named_constructor.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#![warn(clippy::self_named_constructor)]
|
||||||
|
|
||||||
|
struct ShouldSpawn;
|
||||||
|
struct ShouldNotSpawn;
|
||||||
|
|
||||||
|
impl ShouldSpawn {
|
||||||
|
pub fn should_spawn() -> ShouldSpawn {
|
||||||
|
ShouldSpawn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn should_not_spawn() -> ShouldNotSpawn {
|
||||||
|
ShouldNotSpawn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShouldNotSpawn {
|
||||||
|
pub fn new() -> ShouldNotSpawn {
|
||||||
|
ShouldNotSpawn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ShouldNotSpawnWithTrait;
|
||||||
|
|
||||||
|
trait ShouldNotSpawnTrait {
|
||||||
|
type Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShouldNotSpawnTrait for ShouldNotSpawnWithTrait {
|
||||||
|
type Item = Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShouldNotSpawnWithTrait {
|
||||||
|
pub fn should_not_spawn_with_trait() -> impl ShouldNotSpawnTrait<Item = Self> {
|
||||||
|
ShouldNotSpawnWithTrait
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same trait name and same type name should not spawn the lint
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Default;
|
||||||
|
|
||||||
|
trait TraitSameTypeName {
|
||||||
|
fn should_not_spawn() -> Self;
|
||||||
|
}
|
||||||
|
impl TraitSameTypeName for ShouldNotSpawn {
|
||||||
|
fn should_not_spawn() -> Self {
|
||||||
|
ShouldNotSpawn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SelfMethodShouldNotSpawn;
|
||||||
|
|
||||||
|
impl SelfMethodShouldNotSpawn {
|
||||||
|
fn self_method_should_not_spawn(self) -> Self {
|
||||||
|
SelfMethodShouldNotSpawn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
12
tests/ui/self_named_constructor.stderr
Normal file
12
tests/ui/self_named_constructor.stderr
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
error: constructor `should_spawn` has the same name as the type
|
||||||
|
--> $DIR/self_named_constructor.rs:7:5
|
||||||
|
|
|
||||||
|
LL | / pub fn should_spawn() -> ShouldSpawn {
|
||||||
|
LL | | ShouldSpawn
|
||||||
|
LL | | }
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
= note: `-D clippy::self-named-constructor` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: suspicious use of binary operator in `Add` impl
|
error: suspicious use of `-` in `Add` impl
|
||||||
--> $DIR/suspicious_arithmetic_impl.rs:13:20
|
--> $DIR/suspicious_arithmetic_impl.rs:13:20
|
||||||
|
|
|
|
||||||
LL | Foo(self.0 - other.0)
|
LL | Foo(self.0 - other.0)
|
||||||
|
@ -6,7 +6,7 @@ LL | Foo(self.0 - other.0)
|
||||||
|
|
|
|
||||||
= note: `-D clippy::suspicious-arithmetic-impl` implied by `-D warnings`
|
= note: `-D clippy::suspicious-arithmetic-impl` implied by `-D warnings`
|
||||||
|
|
||||||
error: suspicious use of binary operator in `AddAssign` impl
|
error: suspicious use of `-` in `AddAssign` impl
|
||||||
--> $DIR/suspicious_arithmetic_impl.rs:19:23
|
--> $DIR/suspicious_arithmetic_impl.rs:19:23
|
||||||
|
|
|
|
||||||
LL | *self = *self - other;
|
LL | *self = *self - other;
|
||||||
|
@ -14,43 +14,43 @@ LL | *self = *self - other;
|
||||||
|
|
|
|
||||||
= note: `-D clippy::suspicious-op-assign-impl` implied by `-D warnings`
|
= note: `-D clippy::suspicious-op-assign-impl` implied by `-D warnings`
|
||||||
|
|
||||||
error: suspicious use of binary operator in `MulAssign` impl
|
error: suspicious use of `/` in `MulAssign` impl
|
||||||
--> $DIR/suspicious_arithmetic_impl.rs:32:16
|
--> $DIR/suspicious_arithmetic_impl.rs:32:16
|
||||||
|
|
|
|
||||||
LL | self.0 /= other.0;
|
LL | self.0 /= other.0;
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: suspicious use of binary operator in `Rem` impl
|
error: suspicious use of `/` in `Rem` impl
|
||||||
--> $DIR/suspicious_arithmetic_impl.rs:70:20
|
--> $DIR/suspicious_arithmetic_impl.rs:70:20
|
||||||
|
|
|
|
||||||
LL | Foo(self.0 / other.0)
|
LL | Foo(self.0 / other.0)
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: suspicious use of binary operator in `BitAnd` impl
|
error: suspicious use of `|` in `BitAnd` impl
|
||||||
--> $DIR/suspicious_arithmetic_impl.rs:78:20
|
--> $DIR/suspicious_arithmetic_impl.rs:78:20
|
||||||
|
|
|
|
||||||
LL | Foo(self.0 | other.0)
|
LL | Foo(self.0 | other.0)
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: suspicious use of binary operator in `BitOr` impl
|
error: suspicious use of `^` in `BitOr` impl
|
||||||
--> $DIR/suspicious_arithmetic_impl.rs:86:20
|
--> $DIR/suspicious_arithmetic_impl.rs:86:20
|
||||||
|
|
|
|
||||||
LL | Foo(self.0 ^ other.0)
|
LL | Foo(self.0 ^ other.0)
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: suspicious use of binary operator in `BitXor` impl
|
error: suspicious use of `&` in `BitXor` impl
|
||||||
--> $DIR/suspicious_arithmetic_impl.rs:94:20
|
--> $DIR/suspicious_arithmetic_impl.rs:94:20
|
||||||
|
|
|
|
||||||
LL | Foo(self.0 & other.0)
|
LL | Foo(self.0 & other.0)
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: suspicious use of binary operator in `Shl` impl
|
error: suspicious use of `>>` in `Shl` impl
|
||||||
--> $DIR/suspicious_arithmetic_impl.rs:102:20
|
--> $DIR/suspicious_arithmetic_impl.rs:102:20
|
||||||
|
|
|
|
||||||
LL | Foo(self.0 >> other.0)
|
LL | Foo(self.0 >> other.0)
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: suspicious use of binary operator in `Shr` impl
|
error: suspicious use of `<<` in `Shr` impl
|
||||||
--> $DIR/suspicious_arithmetic_impl.rs:110:20
|
--> $DIR/suspicious_arithmetic_impl.rs:110:20
|
||||||
|
|
|
|
||||||
LL | Foo(self.0 << other.0)
|
LL | Foo(self.0 << other.0)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#![warn(clippy::temporary_assignment)]
|
#![warn(clippy::temporary_assignment)]
|
||||||
#![allow(const_item_mutation)]
|
|
||||||
|
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: assignment to temporary
|
error: assignment to temporary
|
||||||
--> $DIR/temporary_assignment.rs:48:5
|
--> $DIR/temporary_assignment.rs:47:5
|
||||||
|
|
|
|
||||||
LL | Struct { field: 0 }.field = 1;
|
LL | Struct { field: 0 }.field = 1;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -7,7 +7,7 @@ LL | Struct { field: 0 }.field = 1;
|
||||||
= note: `-D clippy::temporary-assignment` implied by `-D warnings`
|
= note: `-D clippy::temporary-assignment` implied by `-D warnings`
|
||||||
|
|
||||||
error: assignment to temporary
|
error: assignment to temporary
|
||||||
--> $DIR/temporary_assignment.rs:49:5
|
--> $DIR/temporary_assignment.rs:48:5
|
||||||
|
|
|
|
||||||
LL | / MultiStruct {
|
LL | / MultiStruct {
|
||||||
LL | | structure: Struct { field: 0 },
|
LL | | structure: Struct { field: 0 },
|
||||||
|
@ -17,13 +17,13 @@ LL | | .field = 1;
|
||||||
| |______________^
|
| |______________^
|
||||||
|
|
||||||
error: assignment to temporary
|
error: assignment to temporary
|
||||||
--> $DIR/temporary_assignment.rs:54:5
|
--> $DIR/temporary_assignment.rs:53:5
|
||||||
|
|
|
|
||||||
LL | ArrayStruct { array: [0] }.array[0] = 1;
|
LL | ArrayStruct { array: [0] }.array[0] = 1;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: assignment to temporary
|
error: assignment to temporary
|
||||||
--> $DIR/temporary_assignment.rs:55:5
|
--> $DIR/temporary_assignment.rs:54:5
|
||||||
|
|
|
|
||||||
LL | (0, 0).0 = 1;
|
LL | (0, 0).0 = 1;
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
clippy::unused_unit,
|
clippy::unused_unit,
|
||||||
clippy::unnecessary_wraps,
|
clippy::unnecessary_wraps,
|
||||||
clippy::or_fun_call,
|
clippy::or_fun_call,
|
||||||
clippy::needless_question_mark
|
clippy::needless_question_mark,
|
||||||
|
clippy::self_named_constructor
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: passing a unit value to a function
|
error: passing a unit value to a function
|
||||||
--> $DIR/unit_arg.rs:55:5
|
--> $DIR/unit_arg.rs:56:5
|
||||||
|
|
|
|
||||||
LL | / foo({
|
LL | / foo({
|
||||||
LL | | 1;
|
LL | | 1;
|
||||||
|
@ -20,7 +20,7 @@ LL | foo(());
|
||||||
|
|
|
|
||||||
|
|
||||||
error: passing a unit value to a function
|
error: passing a unit value to a function
|
||||||
--> $DIR/unit_arg.rs:58:5
|
--> $DIR/unit_arg.rs:59:5
|
||||||
|
|
|
|
||||||
LL | foo(foo(1));
|
LL | foo(foo(1));
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
@ -32,7 +32,7 @@ LL | foo(());
|
||||||
|
|
|
|
||||||
|
|
||||||
error: passing a unit value to a function
|
error: passing a unit value to a function
|
||||||
--> $DIR/unit_arg.rs:59:5
|
--> $DIR/unit_arg.rs:60:5
|
||||||
|
|
|
|
||||||
LL | / foo({
|
LL | / foo({
|
||||||
LL | | foo(1);
|
LL | | foo(1);
|
||||||
|
@ -54,7 +54,7 @@ LL | foo(());
|
||||||
|
|
|
|
||||||
|
|
||||||
error: passing a unit value to a function
|
error: passing a unit value to a function
|
||||||
--> $DIR/unit_arg.rs:64:5
|
--> $DIR/unit_arg.rs:65:5
|
||||||
|
|
|
|
||||||
LL | / b.bar({
|
LL | / b.bar({
|
||||||
LL | | 1;
|
LL | | 1;
|
||||||
|
@ -74,7 +74,7 @@ LL | b.bar(());
|
||||||
|
|
|
|
||||||
|
|
||||||
error: passing unit values to a function
|
error: passing unit values to a function
|
||||||
--> $DIR/unit_arg.rs:67:5
|
--> $DIR/unit_arg.rs:68:5
|
||||||
|
|
|
|
||||||
LL | taking_multiple_units(foo(0), foo(1));
|
LL | taking_multiple_units(foo(0), foo(1));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -87,7 +87,7 @@ LL | taking_multiple_units((), ());
|
||||||
|
|
|
|
||||||
|
|
||||||
error: passing unit values to a function
|
error: passing unit values to a function
|
||||||
--> $DIR/unit_arg.rs:68:5
|
--> $DIR/unit_arg.rs:69:5
|
||||||
|
|
|
|
||||||
LL | / taking_multiple_units(foo(0), {
|
LL | / taking_multiple_units(foo(0), {
|
||||||
LL | | foo(1);
|
LL | | foo(1);
|
||||||
|
@ -110,7 +110,7 @@ LL | taking_multiple_units((), ());
|
||||||
|
|
|
|
||||||
|
|
||||||
error: passing unit values to a function
|
error: passing unit values to a function
|
||||||
--> $DIR/unit_arg.rs:72:5
|
--> $DIR/unit_arg.rs:73:5
|
||||||
|
|
|
|
||||||
LL | / taking_multiple_units(
|
LL | / taking_multiple_units(
|
||||||
LL | | {
|
LL | | {
|
||||||
|
@ -140,7 +140,7 @@ LL | foo(2);
|
||||||
...
|
...
|
||||||
|
|
||||||
error: passing a unit value to a function
|
error: passing a unit value to a function
|
||||||
--> $DIR/unit_arg.rs:83:13
|
--> $DIR/unit_arg.rs:84:13
|
||||||
|
|
|
|
||||||
LL | None.or(Some(foo(2)));
|
LL | None.or(Some(foo(2)));
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -154,7 +154,7 @@ LL | });
|
||||||
|
|
|
|
||||||
|
|
||||||
error: passing a unit value to a function
|
error: passing a unit value to a function
|
||||||
--> $DIR/unit_arg.rs:86:5
|
--> $DIR/unit_arg.rs:87:5
|
||||||
|
|
|
|
||||||
LL | foo(foo(()));
|
LL | foo(foo(()));
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -166,7 +166,7 @@ LL | foo(());
|
||||||
|
|
|
|
||||||
|
|
||||||
error: passing a unit value to a function
|
error: passing a unit value to a function
|
||||||
--> $DIR/unit_arg.rs:123:5
|
--> $DIR/unit_arg.rs:124:5
|
||||||
|
|
|
|
||||||
LL | Some(foo(1))
|
LL | Some(foo(1))
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
@ -4,7 +4,12 @@
|
||||||
|
|
||||||
#![warn(clippy::use_self)]
|
#![warn(clippy::use_self)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(clippy::should_implement_trait, clippy::upper_case_acronyms, clippy::from_over_into)]
|
#![allow(
|
||||||
|
clippy::should_implement_trait,
|
||||||
|
clippy::upper_case_acronyms,
|
||||||
|
clippy::from_over_into,
|
||||||
|
clippy::self_named_constructor
|
||||||
|
)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate proc_macro_derive;
|
extern crate proc_macro_derive;
|
||||||
|
|
|
@ -4,7 +4,12 @@
|
||||||
|
|
||||||
#![warn(clippy::use_self)]
|
#![warn(clippy::use_self)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(clippy::should_implement_trait, clippy::upper_case_acronyms, clippy::from_over_into)]
|
#![allow(
|
||||||
|
clippy::should_implement_trait,
|
||||||
|
clippy::upper_case_acronyms,
|
||||||
|
clippy::from_over_into,
|
||||||
|
clippy::self_named_constructor
|
||||||
|
)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate proc_macro_derive;
|
extern crate proc_macro_derive;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:18:21
|
--> $DIR/use_self.rs:23:21
|
||||||
|
|
|
|
||||||
LL | fn new() -> Foo {
|
LL | fn new() -> Foo {
|
||||||
| ^^^ help: use the applicable keyword: `Self`
|
| ^^^ help: use the applicable keyword: `Self`
|
||||||
|
@ -7,163 +7,163 @@ LL | fn new() -> Foo {
|
||||||
= note: `-D clippy::use-self` implied by `-D warnings`
|
= note: `-D clippy::use-self` implied by `-D warnings`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:19:13
|
--> $DIR/use_self.rs:24:13
|
||||||
|
|
|
|
||||||
LL | Foo {}
|
LL | Foo {}
|
||||||
| ^^^ help: use the applicable keyword: `Self`
|
| ^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:21:22
|
--> $DIR/use_self.rs:26:22
|
||||||
|
|
|
|
||||||
LL | fn test() -> Foo {
|
LL | fn test() -> Foo {
|
||||||
| ^^^ help: use the applicable keyword: `Self`
|
| ^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:22:13
|
--> $DIR/use_self.rs:27:13
|
||||||
|
|
|
|
||||||
LL | Foo::new()
|
LL | Foo::new()
|
||||||
| ^^^ help: use the applicable keyword: `Self`
|
| ^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:27:25
|
--> $DIR/use_self.rs:32:25
|
||||||
|
|
|
|
||||||
LL | fn default() -> Foo {
|
LL | fn default() -> Foo {
|
||||||
| ^^^ help: use the applicable keyword: `Self`
|
| ^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:28:13
|
--> $DIR/use_self.rs:33:13
|
||||||
|
|
|
|
||||||
LL | Foo::new()
|
LL | Foo::new()
|
||||||
| ^^^ help: use the applicable keyword: `Self`
|
| ^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:93:24
|
--> $DIR/use_self.rs:98:24
|
||||||
|
|
|
|
||||||
LL | fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
|
LL | fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
|
||||||
| ^^^ help: use the applicable keyword: `Self`
|
| ^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:93:55
|
--> $DIR/use_self.rs:98:55
|
||||||
|
|
|
|
||||||
LL | fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
|
LL | fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
|
||||||
| ^^^ help: use the applicable keyword: `Self`
|
| ^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:108:13
|
--> $DIR/use_self.rs:113:13
|
||||||
|
|
|
|
||||||
LL | TS(0)
|
LL | TS(0)
|
||||||
| ^^ help: use the applicable keyword: `Self`
|
| ^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:143:29
|
--> $DIR/use_self.rs:148:29
|
||||||
|
|
|
|
||||||
LL | fn bar() -> Bar {
|
LL | fn bar() -> Bar {
|
||||||
| ^^^ help: use the applicable keyword: `Self`
|
| ^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:144:21
|
--> $DIR/use_self.rs:149:21
|
||||||
|
|
|
|
||||||
LL | Bar { foo: Foo {} }
|
LL | Bar { foo: Foo {} }
|
||||||
| ^^^ help: use the applicable keyword: `Self`
|
| ^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:155:21
|
--> $DIR/use_self.rs:160:21
|
||||||
|
|
|
|
||||||
LL | fn baz() -> Foo {
|
LL | fn baz() -> Foo {
|
||||||
| ^^^ help: use the applicable keyword: `Self`
|
| ^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:156:13
|
--> $DIR/use_self.rs:161:13
|
||||||
|
|
|
|
||||||
LL | Foo {}
|
LL | Foo {}
|
||||||
| ^^^ help: use the applicable keyword: `Self`
|
| ^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:173:21
|
--> $DIR/use_self.rs:178:21
|
||||||
|
|
|
|
||||||
LL | let _ = Enum::B(42);
|
LL | let _ = Enum::B(42);
|
||||||
| ^^^^ help: use the applicable keyword: `Self`
|
| ^^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:174:21
|
--> $DIR/use_self.rs:179:21
|
||||||
|
|
|
|
||||||
LL | let _ = Enum::C { field: true };
|
LL | let _ = Enum::C { field: true };
|
||||||
| ^^^^ help: use the applicable keyword: `Self`
|
| ^^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:175:21
|
--> $DIR/use_self.rs:180:21
|
||||||
|
|
|
|
||||||
LL | let _ = Enum::A;
|
LL | let _ = Enum::A;
|
||||||
| ^^^^ help: use the applicable keyword: `Self`
|
| ^^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:217:13
|
--> $DIR/use_self.rs:222:13
|
||||||
|
|
|
|
||||||
LL | nested::A::fun_1();
|
LL | nested::A::fun_1();
|
||||||
| ^^^^^^^^^ help: use the applicable keyword: `Self`
|
| ^^^^^^^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:218:13
|
--> $DIR/use_self.rs:223:13
|
||||||
|
|
|
|
||||||
LL | nested::A::A;
|
LL | nested::A::A;
|
||||||
| ^^^^^^^^^ help: use the applicable keyword: `Self`
|
| ^^^^^^^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:220:13
|
--> $DIR/use_self.rs:225:13
|
||||||
|
|
|
|
||||||
LL | nested::A {};
|
LL | nested::A {};
|
||||||
| ^^^^^^^^^ help: use the applicable keyword: `Self`
|
| ^^^^^^^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:239:13
|
--> $DIR/use_self.rs:244:13
|
||||||
|
|
|
|
||||||
LL | TestStruct::from_something()
|
LL | TestStruct::from_something()
|
||||||
| ^^^^^^^^^^ help: use the applicable keyword: `Self`
|
| ^^^^^^^^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:253:25
|
--> $DIR/use_self.rs:258:25
|
||||||
|
|
|
|
||||||
LL | async fn g() -> S {
|
LL | async fn g() -> S {
|
||||||
| ^ help: use the applicable keyword: `Self`
|
| ^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:254:13
|
--> $DIR/use_self.rs:259:13
|
||||||
|
|
|
|
||||||
LL | S {}
|
LL | S {}
|
||||||
| ^ help: use the applicable keyword: `Self`
|
| ^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:258:16
|
--> $DIR/use_self.rs:263:16
|
||||||
|
|
|
|
||||||
LL | &p[S::A..S::B]
|
LL | &p[S::A..S::B]
|
||||||
| ^ help: use the applicable keyword: `Self`
|
| ^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:258:22
|
--> $DIR/use_self.rs:263:22
|
||||||
|
|
|
|
||||||
LL | &p[S::A..S::B]
|
LL | &p[S::A..S::B]
|
||||||
| ^ help: use the applicable keyword: `Self`
|
| ^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:281:29
|
--> $DIR/use_self.rs:286:29
|
||||||
|
|
|
|
||||||
LL | fn foo(value: T) -> Foo<T> {
|
LL | fn foo(value: T) -> Foo<T> {
|
||||||
| ^^^^^^ help: use the applicable keyword: `Self`
|
| ^^^^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:282:13
|
--> $DIR/use_self.rs:287:13
|
||||||
|
|
|
|
||||||
LL | Foo::<T> { value }
|
LL | Foo::<T> { value }
|
||||||
| ^^^^^^^^ help: use the applicable keyword: `Self`
|
| ^^^^^^^^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:454:13
|
--> $DIR/use_self.rs:459:13
|
||||||
|
|
|
|
||||||
LL | A::new::<submod::B>(submod::B {})
|
LL | A::new::<submod::B>(submod::B {})
|
||||||
| ^ help: use the applicable keyword: `Self`
|
| ^ help: use the applicable keyword: `Self`
|
||||||
|
|
||||||
error: unnecessary structure name repetition
|
error: unnecessary structure name repetition
|
||||||
--> $DIR/use_self.rs:491:13
|
--> $DIR/use_self.rs:496:13
|
||||||
|
|
|
|
||||||
LL | S2::new()
|
LL | S2::new()
|
||||||
| ^^ help: use the applicable keyword: `Self`
|
| ^^ help: use the applicable keyword: `Self`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue