From f882c363e2ff2ab7b0a3cf8e95b88e0909e68230 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 18 Jul 2021 07:57:03 -0700 Subject: [PATCH 01/10] fix(clippy): add missing allow(dyn_drop) --- tests/ui/needless_lifetimes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs index bda0801e51c7..1d77382bf2cd 100644 --- a/tests/ui/needless_lifetimes.rs +++ b/tests/ui/needless_lifetimes.rs @@ -1,5 +1,5 @@ #![warn(clippy::needless_lifetimes)] -#![allow(dead_code, clippy::needless_pass_by_value, clippy::unnecessary_wraps)] +#![allow(dead_code, clippy::needless_pass_by_value, clippy::unnecessary_wraps, dyn_drop)] fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} From 884ef4c287480704e0176930347563410eb8907f Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 19 Jul 2021 11:52:05 +0200 Subject: [PATCH 02/10] Merge commit '4c41a222ca5d1325fb4b6709395bd06e766cc042' into clippyup --- CHANGELOG.md | 1 + clippy_lints/src/assign_ops.rs | 93 ++++-------- clippy_lints/src/eq_op.rs | 2 +- clippy_lints/src/lib.rs | 5 + clippy_lints/src/matches.rs | 4 +- clippy_lints/src/self_named_constructor.rs | 91 +++++++++++ clippy_lints/src/suspicious_trait_impl.rs | 143 ++++-------------- clippy_lints/src/zero_sized_map_values.rs | 5 +- clippy_utils/src/higher.rs | 25 --- clippy_utils/src/lib.rs | 47 ++++-- clippy_utils/src/sugg.rs | 2 +- clippy_utils/src/ty.rs | 6 +- doc/basics.md | 42 +++++ rust-toolchain | 2 +- tests/ui/crashes/ice-6179.rs | 2 +- tests/ui/crashes/ice-7340.rs | 6 + tests/ui/crashes/ice-7410.rs | 31 ++++ tests/ui/issue-7447.rs | 25 +++ tests/ui/issue_4266.rs | 4 +- tests/ui/missing-doc-impl.rs | 4 +- tests/ui/missing-doc-impl.stderr | 12 +- .../ui/missing_const_for_fn/cant_be_const.rs | 2 +- tests/ui/needless_bool/fixable.fixed | 3 +- tests/ui/needless_bool/fixable.rs | 3 +- tests/ui/needless_bool/fixable.stderr | 24 +-- tests/ui/self_named_constructor.rs | 59 ++++++++ tests/ui/self_named_constructor.stderr | 12 ++ tests/ui/suspicious_arithmetic_impl.stderr | 18 +-- tests/ui/unit_arg.rs | 3 +- tests/ui/unit_arg.stderr | 20 +-- tests/ui/use_self.fixed | 7 +- tests/ui/use_self.rs | 7 +- tests/ui/use_self.stderr | 56 +++---- 33 files changed, 468 insertions(+), 298 deletions(-) create mode 100644 clippy_lints/src/self_named_constructor.rs create mode 100644 tests/ui/crashes/ice-7340.rs create mode 100644 tests/ui/crashes/ice-7410.rs create mode 100644 tests/ui/issue-7447.rs create mode 100644 tests/ui/self_named_constructor.rs create mode 100644 tests/ui/self_named_constructor.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f89f74e7450..5e00dec2e775 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2772,6 +2772,7 @@ Released 2018-09-13 [`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 [`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 [`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 diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index a8c527fe2e35..17ce3cd809f6 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_opt; use clippy_utils::ty::implements_trait; -use clippy_utils::{eq_expr_value, get_trait_def_id, trait_ref_of_method}; -use clippy_utils::{higher, paths, sugg}; +use clippy_utils::{binop_traits, sugg}; +use clippy_utils::{eq_expr_value, trait_ref_of_method}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -85,71 +85,34 @@ impl<'tcx> LateLintPass<'tcx> for AssignOps { let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| { let ty = cx.typeck_results().expr_ty(assignee); let rty = cx.typeck_results().expr_ty(rhs); - macro_rules! ops { - ($op:expr, - $cx:expr, - $ty:expr, - $rty:expr, - $($trait_name:ident),+) => { - match $op { - $(hir::BinOpKind::$trait_name => { - let [krate, module] = paths::OPS_MODULE; - let path: [&str; 3] = [krate, module, concat!(stringify!($trait_name), "Assign")]; - let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) { - trait_id - } else { - return; // useless if the trait doesn't exist - }; - // check that we are not inside an `impl AssignOp` of this exact operation - let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id); - if_chain! { - if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn); - if trait_ref.path.res.def_id() == trait_id; - then { return; } + if_chain! { + if let Some((_, lang_item)) = binop_traits(op.node); + if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item); + let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id); + if trait_ref_of_method(cx, parent_fn) + .map_or(true, |t| t.path.res.def_id() != trait_id); + if implements_trait(cx, ty, trait_id, &[rty.into()]); + then { + 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, + ); } - 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 { @@ -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)) { let a = &sugg::Sugg::hir(cx, assignee, ".."); 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( expr.span, &format!( diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index a3a8e748d99a..d39cabfb2825 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { if macro_with_not_op(&left.kind) || macro_with_not_op(&right.kind) { 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( cx, EQ_OP, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1af3a215f446..aa763b5c5e66 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -330,6 +330,7 @@ mod regex; mod repeat_once; mod returns; mod self_assignment; +mod self_named_constructor; mod semicolon_if_nothing_returned; mod serde_api; mod shadow; @@ -900,6 +901,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, self_assignment::SELF_ASSIGNMENT, + self_named_constructor::SELF_NAMED_CONSTRUCTOR, semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED, serde_api::SERDE_API_MISUSE, 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::NEEDLESS_RETURN), LintId::of(self_assignment::SELF_ASSIGNMENT), + LintId::of(self_named_constructor::SELF_NAMED_CONSTRUCTOR), LintId::of(serde_api::SERDE_API_MISUSE), LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), 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(returns::LET_AND_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(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), 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(); 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(move || box self_named_constructor::SelfNamedConstructor); } #[rustfmt::skip] diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 6d5ce3373f79..66e3d9578941 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -721,7 +721,7 @@ fn check_single_match_single_pattern( expr: &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); } } @@ -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(b0) = find_bool_lit(&b0_arms[0].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; let if_guard = &b0_arms[0].guard; if if_guard.is_none() || b0_arms.len() == 1; diff --git a/clippy_lints/src/self_named_constructor.rs b/clippy_lints/src/self_named_constructor.rs new file mode 100644 index 000000000000..da991e1d90c8 --- /dev/null +++ b/clippy_lints/src/self_named_constructor.rs @@ -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), + ); + } + } + } +} diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 2203ab57b108..f2bffd553210 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -1,5 +1,5 @@ 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 rustc_hir as hir; 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 { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind { - match binop.node { - hir::BinOpKind::Eq - | hir::BinOpKind::Lt - | hir::BinOpKind::Le - | hir::BinOpKind::Ne - | hir::BinOpKind::Ge - | hir::BinOpKind::Gt => return, - _ => {}, - } + if_chain! { + if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind; + if let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop.node); + if let Ok(binop_trait_id) = cx.tcx.lang_items().require(binop_trait_lang); + if let Ok(op_assign_trait_id) = cx.tcx.lang_items().require(op_assign_trait_lang); // Check for more than one binary operation in the implemented function // Linting when multiple operations are involved can result in false positives 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::ImplItemKind::Fn(_, body_id) = impl_item.kind; - then { - let body = cx.tcx.hir().body(body_id); - let mut visitor = BinaryExprVisitor { nb_binops: 0 }; - walk_expr(&mut visitor, &body.value); - if visitor.nb_binops > 1 { - return; - } - } - } - - if let Some(impl_trait) = check_binop( - cx, - 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, - ], - ) { + if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get(parent_fn); + if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind; + let body = cx.tcx.hir().body(body_id); + let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id); + if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn); + let trait_id = trait_ref.path.res.def_id(); + if ![binop_trait_id, op_assign_trait_id].contains(&trait_id); + if let Some(&(_, lint)) = [ + (&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 count_binops(&body.value) == 1; + then { span_lint( cx, - SUSPICIOUS_ARITHMETIC_IMPL, + lint, binop.span, - &format!("suspicious use of binary operator in `{}` impl", impl_trait), - ); - } - - 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), + &format!("suspicious use of `{}` in `{}` impl", binop.node.as_str(), cx.tcx.item_name(trait_id)), ); } } } } -fn check_binop( - cx: &LateContext<'_>, - expr: &hir::Expr<'_>, - binop: hir::BinOpKind, - 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 +fn count_binops(expr: &hir::Expr<'_>) -> u32 { + let mut visitor = BinaryExprVisitor::default(); + visitor.visit_expr(expr); + visitor.nb_binops } +#[derive(Default)] struct BinaryExprVisitor { nb_binops: u32, } diff --git a/clippy_lints/src/zero_sized_map_values.rs b/clippy_lints/src/zero_sized_map_values.rs index f93f0047f514..053bbc9aea67 100644 --- a/clippy_lints/src/zero_sized_map_values.rs +++ b/clippy_lints/src/zero_sized_map_values.rs @@ -4,7 +4,7 @@ use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item, match_type}; use if_chain::if_chain; use rustc_hir::{self as hir, HirId, ItemKind, Node}; 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_span::sym; 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 let Adt(_, substs) = ty.kind(); 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`. if is_normalizable(cx, cx.param_env, ty); if let Ok(layout) = cx.layout_of(ty); diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs index 3e3e472e99fb..f32f1109b08e 100644 --- a/clippy_utils/src/higher.rs +++ b/clippy_utils/src/higher.rs @@ -11,31 +11,6 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, StmtKind, UnOp}; use rustc_lint::LateContext; 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`. #[derive(Debug, Copy, Clone)] pub struct Range<'a> { diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 4f0a9f442ed9..00db52a9457d 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -909,12 +909,8 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool if is_integer_literal(e, value) { return true; } - let map = cx.tcx.hir(); - let parent_item = map.get_parent_item(e.hir_id); - 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)) - { + let enclosing_body = cx.tcx.hir().local_def_id(cx.tcx.hir().enclosing_body_owner(e.hir_id)); + if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) { value == v } else { false @@ -1041,18 +1037,14 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { PatKind::Struct(ref qpath, fields, _) => { is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat)) }, - PatKind::TupleStruct(ref qpath, pats, _) => { - is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats) - }, + PatKind::TupleStruct(ref qpath, pats, _) => is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats), PatKind::Slice(head, middle, tail) => { match &cx.typeck_results().node_type(pat.hir_id).kind() { rustc_ty::Slice(..) => { // [..] is the only irrefutable slice pattern. !head.is_empty() || middle.is_none() || !tail.is_empty() }, - rustc_ty::Array(..) => { - are_refutable(cx, head.iter().chain(middle).chain(tail.iter())) - }, + rustc_ty::Array(..) => are_refutable(cx, head.iter().chain(middle).chain(tail.iter())), _ => { // unreachable!() 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") } + +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 +} diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index efc0ec50fdc9..3bd75b10e905 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -154,7 +154,7 @@ impl<'a> Sugg<'a> { | hir::ExprKind::Err => Sugg::NonParen(snippet), hir::ExprKind::Assign(..) => Sugg::BinOp(AssocOp::Assign, 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::Type(..) => Sugg::BinOp(AssocOp::Colon, snippet), } diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 3f5c5604d43f..523d55219ab6 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -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 { 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, } } diff --git a/doc/basics.md b/doc/basics.md index e98354358af6..43d3792f5952 100644 --- a/doc/basics.md +++ b/doc/basics.md @@ -14,6 +14,7 @@ the codebase take a look at [Adding Lints] or [Common Tools]. - [lintcheck](#lintcheck) - [PR](#pr) - [Common Abbreviations](#common-abbreviations) + - [Install from source](#install-from-source) ## 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 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 +``` + +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 diff --git a/rust-toolchain b/rust-toolchain index bf9cfb61b46d..3a2005e78722 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-07-15" +channel = "nightly-2021-07-19" components = ["llvm-tools-preview", "rustc-dev", "rust-src"] diff --git a/tests/ui/crashes/ice-6179.rs b/tests/ui/crashes/ice-6179.rs index f8c866a49aa2..8d9a1af8ff11 100644 --- a/tests/ui/crashes/ice-6179.rs +++ b/tests/ui/crashes/ice-6179.rs @@ -7,7 +7,7 @@ struct Foo {} impl Foo { - fn foo() -> Self { + fn new() -> Self { impl Foo { fn bar() {} } diff --git a/tests/ui/crashes/ice-7340.rs b/tests/ui/crashes/ice-7340.rs new file mode 100644 index 000000000000..7d2351d606f1 --- /dev/null +++ b/tests/ui/crashes/ice-7340.rs @@ -0,0 +1,6 @@ +#![allow(clippy::no_effect)] + +fn main() { + const CONSTANT: usize = 8; + [1; 1 % CONSTANT]; +} diff --git a/tests/ui/crashes/ice-7410.rs b/tests/ui/crashes/ice-7410.rs new file mode 100644 index 000000000000..aaa422d88c3e --- /dev/null +++ b/tests/ui/crashes/ice-7410.rs @@ -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() {} diff --git a/tests/ui/issue-7447.rs b/tests/ui/issue-7447.rs new file mode 100644 index 000000000000..fdb77f322579 --- /dev/null +++ b/tests/ui/issue-7447.rs @@ -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, Vec>> { + todo!() +} + +struct Mmap; + +enum ByteViewBacking<'a> { + Buf(Cow<'a, [u8]>), + Mmap(Mmap), +} + +pub struct ByteView<'a> { + backing: Arc>, +} + +fn main() { + byte_view(panic!()); + group_entries(panic!()); +} diff --git a/tests/ui/issue_4266.rs b/tests/ui/issue_4266.rs index 8a9d5a3d1d56..cc699b79e433 100644 --- a/tests/ui/issue_4266.rs +++ b/tests/ui/issue_4266.rs @@ -25,7 +25,9 @@ async fn all_to_one<'a>(a: &'a str, _b: &'a str) -> &'a str { struct Foo; impl Foo { // ok - pub async fn foo(&mut self) {} + pub async fn new(&mut self) -> Self { + Foo {} + } } // rust-lang/rust#61115 diff --git a/tests/ui/missing-doc-impl.rs b/tests/ui/missing-doc-impl.rs index bfa9ef01b0e9..d5724bf661c6 100644 --- a/tests/ui/missing-doc-impl.rs +++ b/tests/ui/missing-doc-impl.rs @@ -59,7 +59,9 @@ pub trait E: Sized { } impl Foo { - pub fn foo() {} + pub fn new() -> Self { + Foo { a: 0, b: 0 } + } fn bar() {} } diff --git a/tests/ui/missing-doc-impl.stderr b/tests/ui/missing-doc-impl.stderr index d33d512475b2..bda63d66a174 100644 --- a/tests/ui/missing-doc-impl.stderr +++ b/tests/ui/missing-doc-impl.stderr @@ -78,23 +78,25 @@ LL | type AssociatedTypeDef = Self; error: missing documentation for an associated function --> $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 - --> $DIR/missing-doc-impl.rs:63:5 + --> $DIR/missing-doc-impl.rs:65:5 | LL | fn bar() {} | ^^^^^^^^^^^ 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() {} | ^^^^^^^^^^^^^^^ 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 | | 1 diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index 7cda1aaa3c22..6d2cbb6ad96f 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -84,7 +84,7 @@ mod with_drop { impl A { // This can not be const because the type implements `Drop`. - pub fn a(self) -> B { + pub fn b(self) -> B { B } } diff --git a/tests/ui/needless_bool/fixable.fixed b/tests/ui/needless_bool/fixable.fixed index 567dbc54100a..5917ffc3e12e 100644 --- a/tests/ui/needless_bool/fixable.fixed +++ b/tests/ui/needless_bool/fixable.fixed @@ -6,7 +6,8 @@ dead_code, clippy::no_effect, clippy::if_same_then_else, - clippy::needless_return + clippy::needless_return, + clippy::self_named_constructor )] use std::cell::Cell; diff --git a/tests/ui/needless_bool/fixable.rs b/tests/ui/needless_bool/fixable.rs index 10126ad4dbb1..d26dcb9fcc33 100644 --- a/tests/ui/needless_bool/fixable.rs +++ b/tests/ui/needless_bool/fixable.rs @@ -6,7 +6,8 @@ dead_code, clippy::no_effect, clippy::if_same_then_else, - clippy::needless_return + clippy::needless_return, + clippy::self_named_constructor )] use std::cell::Cell; diff --git a/tests/ui/needless_bool/fixable.stderr b/tests/ui/needless_bool/fixable.stderr index 25abfb2a472b..8026d643c448 100644 --- a/tests/ui/needless_bool/fixable.stderr +++ b/tests/ui/needless_bool/fixable.stderr @@ -1,5 +1,5 @@ error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:39:5 + --> $DIR/fixable.rs:40:5 | LL | / if x { LL | | true @@ -11,7 +11,7 @@ LL | | }; = note: `-D clippy::needless-bool` implied by `-D warnings` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:44:5 + --> $DIR/fixable.rs:45:5 | LL | / if x { LL | | false @@ -21,7 +21,7 @@ LL | | }; | |_____^ help: you can reduce it to: `!x` 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 | | false @@ -31,7 +31,7 @@ LL | | }; | |_____^ help: you can reduce it to: `!(x && y)` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:69:5 + --> $DIR/fixable.rs:70:5 | LL | / if x { LL | | return true; @@ -41,7 +41,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return x` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:77:5 + --> $DIR/fixable.rs:78:5 | LL | / if x { LL | | return false; @@ -51,7 +51,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return !x` 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 | | return true; @@ -61,7 +61,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return x && y` 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 | | return false; @@ -71,7 +71,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return !(x && y)` error: equality checks against true are unnecessary - --> $DIR/fixable.rs:101:8 + --> $DIR/fixable.rs:102:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` @@ -79,25 +79,25 @@ LL | if x == true {}; = note: `-D clippy::bool-comparison` implied by `-D warnings` 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 {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/fixable.rs:115:8 + --> $DIR/fixable.rs:116:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` 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 {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` 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() { | ____________^ diff --git a/tests/ui/self_named_constructor.rs b/tests/ui/self_named_constructor.rs new file mode 100644 index 000000000000..7658b86a8d6d --- /dev/null +++ b/tests/ui/self_named_constructor.rs @@ -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 { + 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() {} diff --git a/tests/ui/self_named_constructor.stderr b/tests/ui/self_named_constructor.stderr new file mode 100644 index 000000000000..1e2c34ac2f7b --- /dev/null +++ b/tests/ui/self_named_constructor.stderr @@ -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 + diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr index 63fc9ecb79a9..ced1305874e5 100644 --- a/tests/ui/suspicious_arithmetic_impl.stderr +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -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 | 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` -error: suspicious use of binary operator in `AddAssign` impl +error: suspicious use of `-` in `AddAssign` impl --> $DIR/suspicious_arithmetic_impl.rs:19:23 | LL | *self = *self - other; @@ -14,43 +14,43 @@ LL | *self = *self - other; | = 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 | 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 | 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 | 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 | 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 | 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 | 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 | LL | Foo(self.0 << other.0) diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index 938cc3c78597..df0fdaccb344 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -6,7 +6,8 @@ clippy::unused_unit, clippy::unnecessary_wraps, clippy::or_fun_call, - clippy::needless_question_mark + clippy::needless_question_mark, + clippy::self_named_constructor )] use std::fmt::Debug; diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index 354fd51cd6b6..8155c4ae1107 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -1,5 +1,5 @@ error: passing a unit value to a function - --> $DIR/unit_arg.rs:55:5 + --> $DIR/unit_arg.rs:56:5 | LL | / foo({ LL | | 1; @@ -20,7 +20,7 @@ LL | foo(()); | error: passing a unit value to a function - --> $DIR/unit_arg.rs:58:5 + --> $DIR/unit_arg.rs:59:5 | LL | foo(foo(1)); | ^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | foo(()); | error: passing a unit value to a function - --> $DIR/unit_arg.rs:59:5 + --> $DIR/unit_arg.rs:60:5 | LL | / foo({ LL | | foo(1); @@ -54,7 +54,7 @@ LL | foo(()); | error: passing a unit value to a function - --> $DIR/unit_arg.rs:64:5 + --> $DIR/unit_arg.rs:65:5 | LL | / b.bar({ LL | | 1; @@ -74,7 +74,7 @@ LL | b.bar(()); | 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)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL | taking_multiple_units((), ()); | 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 | | foo(1); @@ -110,7 +110,7 @@ LL | taking_multiple_units((), ()); | error: passing unit values to a function - --> $DIR/unit_arg.rs:72:5 + --> $DIR/unit_arg.rs:73:5 | LL | / taking_multiple_units( LL | | { @@ -140,7 +140,7 @@ LL | foo(2); ... 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))); | ^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | }); | error: passing a unit value to a function - --> $DIR/unit_arg.rs:86:5 + --> $DIR/unit_arg.rs:87:5 | LL | foo(foo(())); | ^^^^^^^^^^^^ @@ -166,7 +166,7 @@ LL | foo(()); | error: passing a unit value to a function - --> $DIR/unit_arg.rs:123:5 + --> $DIR/unit_arg.rs:124:5 | LL | Some(foo(1)) | ^^^^^^^^^^^^ diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index e2c28542efc7..23fc7632511c 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -4,7 +4,12 @@ #![warn(clippy::use_self)] #![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] extern crate proc_macro_derive; diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 3cd99b9f5cd8..bb46a3399237 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -4,7 +4,12 @@ #![warn(clippy::use_self)] #![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] extern crate proc_macro_derive; diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 6ac26c9e5a9c..e14368a11aa7 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,5 +1,5 @@ error: unnecessary structure name repetition - --> $DIR/use_self.rs:18:21 + --> $DIR/use_self.rs:23:21 | LL | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` @@ -7,163 +7,163 @@ LL | fn new() -> Foo { = note: `-D clippy::use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/use_self.rs:19:13 + --> $DIR/use_self.rs:24:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:21:22 + --> $DIR/use_self.rs:26:22 | LL | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:22:13 + --> $DIR/use_self.rs:27:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:27:25 + --> $DIR/use_self.rs:32:25 | LL | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:28:13 + --> $DIR/use_self.rs:33:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:93:24 + --> $DIR/use_self.rs:98:24 | LL | fn bad(foos: &[Foo]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:93:55 + --> $DIR/use_self.rs:98:55 | LL | fn bad(foos: &[Foo]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:108:13 + --> $DIR/use_self.rs:113:13 | LL | TS(0) | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:143:29 + --> $DIR/use_self.rs:148:29 | LL | fn bar() -> Bar { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:144:21 + --> $DIR/use_self.rs:149:21 | LL | Bar { foo: Foo {} } | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:155:21 + --> $DIR/use_self.rs:160:21 | LL | fn baz() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:156:13 + --> $DIR/use_self.rs:161:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:173:21 + --> $DIR/use_self.rs:178:21 | LL | let _ = Enum::B(42); | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:174:21 + --> $DIR/use_self.rs:179:21 | LL | let _ = Enum::C { field: true }; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:175:21 + --> $DIR/use_self.rs:180:21 | LL | let _ = Enum::A; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:217:13 + --> $DIR/use_self.rs:222:13 | LL | nested::A::fun_1(); | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:218:13 + --> $DIR/use_self.rs:223:13 | LL | nested::A::A; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:220:13 + --> $DIR/use_self.rs:225:13 | LL | nested::A {}; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:239:13 + --> $DIR/use_self.rs:244:13 | LL | TestStruct::from_something() | ^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:253:25 + --> $DIR/use_self.rs:258:25 | LL | async fn g() -> S { | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:254:13 + --> $DIR/use_self.rs:259:13 | LL | S {} | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:258:16 + --> $DIR/use_self.rs:263:16 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:258:22 + --> $DIR/use_self.rs:263:22 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:281:29 + --> $DIR/use_self.rs:286:29 | LL | fn foo(value: T) -> Foo { | ^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:282:13 + --> $DIR/use_self.rs:287:13 | LL | Foo:: { value } | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:454:13 + --> $DIR/use_self.rs:459:13 | LL | A::new::(submod::B {}) | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:491:13 + --> $DIR/use_self.rs:496:13 | LL | S2::new() | ^^ help: use the applicable keyword: `Self` From 1b8fc8f13d9f3874ae88c482807c24c2218e4179 Mon Sep 17 00:00:00 2001 From: chaz-kiker Date: Fri, 23 Jul 2021 12:30:52 -0500 Subject: [PATCH 03/10] update clippy ui test 'future_not_send.stderr' to match the new diagnostic messages --- tests/ui/future_not_send.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/future_not_send.stderr b/tests/ui/future_not_send.stderr index b59dbb3e76c6..c734051ccf32 100644 --- a/tests/ui/future_not_send.stderr +++ b/tests/ui/future_not_send.stderr @@ -55,11 +55,11 @@ note: captured value is not `Send` LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell) -> bool { | ^^ has type `std::rc::Rc<[u8]>` which is not `Send` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` -note: captured value is not `Send` +note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` --> $DIR/future_not_send.rs:20:40 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell) -> bool { - | ^^^^ has type `&std::cell::Cell` which is not `Send` + | ^^^^ has type `&std::cell::Cell` which is not `Send`, because `std::cell::Cell` is not `Sync` = note: `std::cell::Cell` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely From 00faed9f0cb0129dc39d3f6ea769df35c68a4d05 Mon Sep 17 00:00:00 2001 From: kadmin Date: Sat, 24 Apr 2021 21:41:57 +0000 Subject: [PATCH 04/10] Add generic arg infer --- clippy_utils/src/hir_utils.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index a21ad42c0617..63737955f09b 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -885,7 +885,15 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_ty(&mut self, ty: &Ty<'_>) { std::mem::discriminant(&ty.kind).hash(&mut self.s); - match ty.kind { + self.hash_tykind(&ty.kind); + } + + pub fn hash_infer(&mut self) { + "_".hash(&mut self.s); + } + + pub fn hash_tykind(&mut self, ty: &TyKind<'_>) { + match ty { TyKind::Slice(ty) => { self.hash_ty(ty); }, @@ -949,6 +957,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { GenericArg::Lifetime(l) => self.hash_lifetime(l), GenericArg::Type(ref ty) => self.hash_ty(ty), GenericArg::Const(ref ca) => self.hash_body(ca.value.body), + GenericArg::Infer(ref _inf) => self.hash_infer(), } } } From 8286824ab2f776eeaebd21b1f78bacda34dcbcba Mon Sep 17 00:00:00 2001 From: kadmin Date: Mon, 26 Apr 2021 18:19:23 +0000 Subject: [PATCH 05/10] Add inferred args to typeck --- clippy_lints/src/implicit_hasher.rs | 10 +++- clippy_lints/src/types/type_complexity.rs | 7 ++- clippy_lints/src/use_self.rs | 56 ++++++++++++++++++++++- clippy_utils/src/hir_utils.rs | 8 ++-- clippy_utils/src/ty.rs | 2 +- tests/ui/transmute_ptr_to_ref.stderr | 4 +- 6 files changed, 75 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs index 9a040ca572af..ad4898d1ccbb 100644 --- a/clippy_lints/src/implicit_hasher.rs +++ b/clippy_lints/src/implicit_hasher.rs @@ -5,7 +5,7 @@ use std::collections::BTreeMap; use rustc_errors::DiagnosticBuilder; use rustc_hir as hir; -use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, NestedVisitorMap, Visitor}; +use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, walk_inf, NestedVisitorMap, Visitor}; use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; @@ -295,6 +295,14 @@ impl<'a, 'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> { walk_ty(self, t); } + fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { + if let Some(target) = ImplicitHasherType::new(self.cx, &inf.to_ty()) { + self.found.push(target); + } + + walk_inf(self, inf); + } + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/clippy_lints/src/types/type_complexity.rs b/clippy_lints/src/types/type_complexity.rs index d8c4b67520d1..b438d680d2cb 100644 --- a/clippy_lints/src/types/type_complexity.rs +++ b/clippy_lints/src/types/type_complexity.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint; use rustc_hir as hir; -use rustc_hir::intravisit::{walk_ty, NestedVisitorMap, Visitor}; +use rustc_hir::intravisit::{walk_ty, walk_inf, NestedVisitorMap, Visitor}; use rustc_hir::{GenericParamKind, TyKind}; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; @@ -39,6 +39,11 @@ struct TypeComplexityVisitor { impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { type Map = Map<'tcx>; + fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { + self.score += 1; + walk_inf(self, inf); + } + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) { let (add_score, sub_nest) = match ty.kind { // _, &x and *x have only small overhead; don't mess with nesting level diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 71117e967e31..c8cdf1a5d2c9 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -8,8 +8,9 @@ use rustc_hir::{ self as hir, def::{CtorOf, DefKind, Res}, def_id::LocalDefId, - intravisit::{walk_ty, NestedVisitorMap, Visitor}, - Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Path, QPath, TyKind, + intravisit::{walk_ty, walk_inf, NestedVisitorMap, Visitor}, + Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Node, Path, PathSegment, + QPath, TyKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; @@ -263,6 +264,11 @@ struct SkipTyCollector { impl<'tcx> Visitor<'tcx> for SkipTyCollector { type Map = Map<'tcx>; + fn visit_infer(&mut self, inf: &hir::InferArg) { + self.types_to_skip.push(inf.hir_id); + + walk_inf(self, inf) + } fn visit_ty(&mut self, hir_ty: &hir::Ty<'_>) { self.types_to_skip.push(hir_ty.hir_id); @@ -274,6 +280,52 @@ impl<'tcx> Visitor<'tcx> for SkipTyCollector { } } +<<<<<<< HEAD +======= +struct LintTyCollector<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + self_ty: Ty<'tcx>, + types_to_lint: Vec, + types_to_skip: Vec, +} + +impl<'a, 'tcx> Visitor<'tcx> for LintTyCollector<'a, 'tcx> { + type Map = Map<'tcx>; + + fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'_>) { + if_chain! { + if let Some(ty) = self.cx.typeck_results().node_type_opt(hir_ty.hir_id); + if should_lint_ty(hir_ty, ty, self.self_ty); + then { + self.types_to_lint.push(hir_ty.hir_id); + } else { + self.types_to_skip.push(hir_ty.hir_id); + } + } + + walk_ty(self, hir_ty); + } + + fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { + if_chain! { + if let Some(ty) = self.cx.typeck_results().node_type_opt(inf.hir_id); + if should_lint_ty(&inf.to_ty(), ty, self.self_ty); + then { + self.types_to_lint.push(inf.hir_id); + } else { + self.types_to_skip.push(inf.hir_id); + } + } + + walk_inf(self, inf) + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } +} + +>>>>>>> Add inferred args to typeck fn span_lint(cx: &LateContext<'_>, span: Span) { span_lint_and_sugg( cx, diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 63737955f09b..e636038b6e1a 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -288,6 +288,8 @@ impl HirEqInterExpr<'_, '_, '_> { (GenericArg::Const(l), GenericArg::Const(r)) => self.eq_body(l.value.body, r.value.body), (GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt), (GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty), + (GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) => + self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()), _ => false, } } @@ -888,10 +890,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_tykind(&ty.kind); } - pub fn hash_infer(&mut self) { - "_".hash(&mut self.s); - } - pub fn hash_tykind(&mut self, ty: &TyKind<'_>) { match ty { TyKind::Slice(ty) => { @@ -957,7 +955,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { GenericArg::Lifetime(l) => self.hash_lifetime(l), GenericArg::Type(ref ty) => self.hash_ty(ty), GenericArg::Const(ref ca) => self.hash_body(ca.value.body), - GenericArg::Infer(ref _inf) => self.hash_infer(), + GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()), } } } diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 523d55219ab6..e914dc1c222f 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -180,7 +180,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { } // FIXME: Per https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/at/struct.At.html#method.normalize -// this function can be removed once the `normalizie` method does not panic when normalization does +// this function can be removed once the `normalize` method does not panic when normalization does // not succeed /// Checks if `Ty` is normalizable. This function is useful /// to avoid crashes on `layout_of`. diff --git a/tests/ui/transmute_ptr_to_ref.stderr b/tests/ui/transmute_ptr_to_ref.stderr index df0598a58cd3..54ab04f8c5d3 100644 --- a/tests/ui/transmute_ptr_to_ref.stderr +++ b/tests/ui/transmute_ptr_to_ref.stderr @@ -46,13 +46,13 @@ error: transmute from a pointer type (`*const i32`) to a reference type (`&issue --> $DIR/transmute_ptr_to_ref.rs:32:32 | LL | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<_>)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const issue1231::Foo)` error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<&u8>`) --> $DIR/transmute_ptr_to_ref.rs:34:33 | LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<&_>)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const issue1231::Foo<&u8>)` error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`) --> $DIR/transmute_ptr_to_ref.rs:38:14 From 5b914f6e33eb93e24534714fa7257a5d8fac5533 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 25 Jul 2021 12:03:24 +0200 Subject: [PATCH 06/10] Introduce OwnerNode::Crate. --- clippy_lints/src/missing_doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index a46a7407df0c..6ad702f8eafd 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -106,7 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) { let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID); - self.check_missing_docs_attrs(cx, attrs, krate.item.inner, "the", "crate"); + self.check_missing_docs_attrs(cx, attrs, krate.module().inner, "the", "crate"); } fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) { From 74379d4d85ad522f68ce2cb37a6a4c061b37ef82 Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 6 May 2021 15:33:44 +0000 Subject: [PATCH 07/10] Actually infer args in visitors --- clippy_lints/src/use_self.rs | 48 +--------------------------- clippy_utils/src/hir_utils.rs | 6 ++-- tests/ui/transmute_ptr_to_ref.stderr | 4 +-- 3 files changed, 6 insertions(+), 52 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index c8cdf1a5d2c9..d5ee717accd2 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -9,7 +9,7 @@ use rustc_hir::{ def::{CtorOf, DefKind, Res}, def_id::LocalDefId, intravisit::{walk_ty, walk_inf, NestedVisitorMap, Visitor}, - Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Node, Path, PathSegment, + Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Path, QPath, TyKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -280,52 +280,6 @@ impl<'tcx> Visitor<'tcx> for SkipTyCollector { } } -<<<<<<< HEAD -======= -struct LintTyCollector<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - self_ty: Ty<'tcx>, - types_to_lint: Vec, - types_to_skip: Vec, -} - -impl<'a, 'tcx> Visitor<'tcx> for LintTyCollector<'a, 'tcx> { - type Map = Map<'tcx>; - - fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'_>) { - if_chain! { - if let Some(ty) = self.cx.typeck_results().node_type_opt(hir_ty.hir_id); - if should_lint_ty(hir_ty, ty, self.self_ty); - then { - self.types_to_lint.push(hir_ty.hir_id); - } else { - self.types_to_skip.push(hir_ty.hir_id); - } - } - - walk_ty(self, hir_ty); - } - - fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { - if_chain! { - if let Some(ty) = self.cx.typeck_results().node_type_opt(inf.hir_id); - if should_lint_ty(&inf.to_ty(), ty, self.self_ty); - then { - self.types_to_lint.push(inf.hir_id); - } else { - self.types_to_skip.push(inf.hir_id); - } - } - - walk_inf(self, inf) - } - - fn nested_visit_map(&mut self) -> NestedVisitorMap { - NestedVisitorMap::None - } -} - ->>>>>>> Add inferred args to typeck fn span_lint(cx: &LateContext<'_>, span: Span) { span_lint_and_sugg( cx, diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index e636038b6e1a..6ea360a88a63 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -904,7 +904,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { mut_ty.mutbl.hash(&mut self.s); }, TyKind::Rptr(lifetime, ref mut_ty) => { - self.hash_lifetime(lifetime); + self.hash_lifetime(*lifetime); self.hash_ty(mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); }, @@ -924,7 +924,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { bfn.decl.c_variadic.hash(&mut self.s); }, TyKind::Tup(ty_list) => { - for ty in ty_list { + for ty in *ty_list { self.hash_ty(ty); } }, @@ -933,7 +933,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_generic_args(arg_list); }, TyKind::TraitObject(_, lifetime, _) => { - self.hash_lifetime(lifetime); + self.hash_lifetime(*lifetime); }, TyKind::Typeof(anon_const) => { self.hash_body(anon_const.body); diff --git a/tests/ui/transmute_ptr_to_ref.stderr b/tests/ui/transmute_ptr_to_ref.stderr index 54ab04f8c5d3..df0598a58cd3 100644 --- a/tests/ui/transmute_ptr_to_ref.stderr +++ b/tests/ui/transmute_ptr_to_ref.stderr @@ -46,13 +46,13 @@ error: transmute from a pointer type (`*const i32`) to a reference type (`&issue --> $DIR/transmute_ptr_to_ref.rs:32:32 | LL | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const issue1231::Foo)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<_>)` error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<&u8>`) --> $DIR/transmute_ptr_to_ref.rs:34:33 | LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const issue1231::Foo<&u8>)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<&_>)` error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`) --> $DIR/transmute_ptr_to_ref.rs:38:14 From 5331fea87543eee06da7eef9f9854e89e9b5c7f3 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Thu, 3 Jun 2021 03:31:27 -0400 Subject: [PATCH 08/10] Update tests --- tests/ui/transmute.rs | 1 - tests/ui/transmute.stderr | 48 +++++++++++++------------- tests/ui/transmute_float_to_int.rs | 1 - tests/ui/transmute_float_to_int.stderr | 12 +++---- 4 files changed, 30 insertions(+), 32 deletions(-) diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 9f1948359e7d..bce4c81b78aa 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -1,4 +1,3 @@ -#![feature(const_fn_transmute)] #![allow(dead_code)] extern crate core; diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index ad9953d12bcc..e31accb982af 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -1,5 +1,5 @@ error: transmute from a type (`&T`) to itself - --> $DIR/transmute.rs:20:20 + --> $DIR/transmute.rs:19:20 | LL | let _: &'a T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,67 +7,67 @@ LL | let _: &'a T = core::intrinsics::transmute(t); = note: `-D clippy::useless-transmute` implied by `-D warnings` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:24:23 + --> $DIR/transmute.rs:23:23 | LL | let _: *const T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:26:21 + --> $DIR/transmute.rs:25:21 | LL | let _: *mut T = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T` error: transmute from a reference to a pointer - --> $DIR/transmute.rs:28:23 + --> $DIR/transmute.rs:27:23 | LL | let _: *const U = core::intrinsics::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U` error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:34:27 + --> $DIR/transmute.rs:33:27 | LL | let _: Vec = core::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:36:27 + --> $DIR/transmute.rs:35:27 | LL | let _: Vec = core::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:38:27 + --> $DIR/transmute.rs:37:27 | LL | let _: Vec = std::intrinsics::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:40:27 + --> $DIR/transmute.rs:39:27 | LL | let _: Vec = std::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> $DIR/transmute.rs:42:27 + --> $DIR/transmute.rs:41:27 | LL | let _: Vec = my_transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^ error: transmute from an integer to a pointer - --> $DIR/transmute.rs:44:31 + --> $DIR/transmute.rs:43:31 | LL | let _: *const usize = std::mem::transmute(5_isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize` error: transmute from an integer to a pointer - --> $DIR/transmute.rs:48:31 + --> $DIR/transmute.rs:47:31 | LL | let _: *const usize = std::mem::transmute(1 + 1usize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize` error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:63:24 + --> $DIR/transmute.rs:62:24 | LL | let _: Usize = core::intrinsics::transmute(int_const_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -75,25 +75,25 @@ LL | let _: Usize = core::intrinsics::transmute(int_const_ptr); = note: `-D clippy::crosspointer-transmute` implied by `-D warnings` error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`) - --> $DIR/transmute.rs:65:24 + --> $DIR/transmute.rs:64:24 | LL | let _: Usize = core::intrinsics::transmute(int_mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`) - --> $DIR/transmute.rs:67:31 + --> $DIR/transmute.rs:66:31 | LL | let _: *const Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) - --> $DIR/transmute.rs:69:29 + --> $DIR/transmute.rs:68:29 | LL | let _: *mut Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a `u32` to a `char` - --> $DIR/transmute.rs:75:28 + --> $DIR/transmute.rs:74:28 | LL | let _: char = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()` @@ -101,13 +101,13 @@ LL | let _: char = unsafe { std::mem::transmute(0_u32) }; = note: `-D clippy::transmute-int-to-char` implied by `-D warnings` error: transmute from a `i32` to a `char` - --> $DIR/transmute.rs:76:28 + --> $DIR/transmute.rs:75:28 | LL | let _: char = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` error: transmute from a `u8` to a `bool` - --> $DIR/transmute.rs:81:28 + --> $DIR/transmute.rs:80:28 | LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` @@ -115,7 +115,7 @@ LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; = note: `-D clippy::transmute-int-to-bool` implied by `-D warnings` error: transmute from a `u32` to a `f32` - --> $DIR/transmute.rs:87:31 + --> $DIR/transmute.rs:86:31 | LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` @@ -123,25 +123,25 @@ LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; = note: `-D clippy::transmute-int-to-float` implied by `-D warnings` error: transmute from a `i32` to a `f32` - --> $DIR/transmute.rs:88:31 + --> $DIR/transmute.rs:87:31 | LL | let _: f32 = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` error: transmute from a `u64` to a `f64` - --> $DIR/transmute.rs:89:31 + --> $DIR/transmute.rs:88:31 | LL | let _: f64 = unsafe { std::mem::transmute(0_u64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_u64)` error: transmute from a `i64` to a `f64` - --> $DIR/transmute.rs:90:31 + --> $DIR/transmute.rs:89:31 | LL | let _: f64 = unsafe { std::mem::transmute(0_i64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)` error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:108:28 + --> $DIR/transmute.rs:107:28 | LL | let _: &str = unsafe { std::mem::transmute(b) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` @@ -149,7 +149,7 @@ LL | let _: &str = unsafe { std::mem::transmute(b) }; = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` error: transmute from a `&mut [u8]` to a `&mut str` - --> $DIR/transmute.rs:109:32 + --> $DIR/transmute.rs:108:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` diff --git a/tests/ui/transmute_float_to_int.rs b/tests/ui/transmute_float_to_int.rs index 1040fee4b34d..806b2d77dc77 100644 --- a/tests/ui/transmute_float_to_int.rs +++ b/tests/ui/transmute_float_to_int.rs @@ -1,4 +1,3 @@ -#![feature(const_fn_transmute)] #![warn(clippy::transmute_float_to_int)] fn float_to_int() { diff --git a/tests/ui/transmute_float_to_int.stderr b/tests/ui/transmute_float_to_int.stderr index 5a40cf381d61..eb786bb39f95 100644 --- a/tests/ui/transmute_float_to_int.stderr +++ b/tests/ui/transmute_float_to_int.stderr @@ -1,5 +1,5 @@ error: transmute from a `f32` to a `u32` - --> $DIR/transmute_float_to_int.rs:5:27 + --> $DIR/transmute_float_to_int.rs:4:27 | LL | let _: u32 = unsafe { std::mem::transmute(1f32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits()` @@ -7,31 +7,31 @@ LL | let _: u32 = unsafe { std::mem::transmute(1f32) }; = note: `-D clippy::transmute-float-to-int` implied by `-D warnings` error: transmute from a `f32` to a `i32` - --> $DIR/transmute_float_to_int.rs:6:27 + --> $DIR/transmute_float_to_int.rs:5:27 | LL | let _: i32 = unsafe { std::mem::transmute(1f32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits() as i32` error: transmute from a `f64` to a `u64` - --> $DIR/transmute_float_to_int.rs:7:27 + --> $DIR/transmute_float_to_int.rs:6:27 | LL | let _: u64 = unsafe { std::mem::transmute(1f64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits()` error: transmute from a `f64` to a `i64` - --> $DIR/transmute_float_to_int.rs:8:27 + --> $DIR/transmute_float_to_int.rs:7:27 | LL | let _: i64 = unsafe { std::mem::transmute(1f64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits() as i64` error: transmute from a `f64` to a `u64` - --> $DIR/transmute_float_to_int.rs:9:27 + --> $DIR/transmute_float_to_int.rs:8:27 | LL | let _: u64 = unsafe { std::mem::transmute(1.0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1.0f64.to_bits()` error: transmute from a `f64` to a `u64` - --> $DIR/transmute_float_to_int.rs:10:27 + --> $DIR/transmute_float_to_int.rs:9:27 | LL | let _: u64 = unsafe { std::mem::transmute(-1.0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-1.0f64).to_bits()` From 7ed7b29d73723b9861b9fe377438c87b607f1222 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 29 Jul 2021 11:14:53 +0200 Subject: [PATCH 09/10] Bump nightly version -> 2021-07-29 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 3a2005e78722..bff657bc1103 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-07-19" +channel = "nightly-2021-07-29" components = ["llvm-tools-preview", "rustc-dev", "rust-src"] From 80116f9009976396d2f821ceeda107ce6b851830 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 29 Jul 2021 11:15:11 +0200 Subject: [PATCH 10/10] Bump Clippy Version -> 0.1.56 --- Cargo.toml | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9b5d9b2adf3b..82e04c8fb854 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.55" +version = "0.1.56" authors = ["The Rust Clippy Developers"] description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 42cf7547f519..0aa5b297442e 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.1.55" +version = "0.1.56" # end automatic update authors = ["The Rust Clippy Developers"] description = "A bunch of helpful lints to avoid common pitfalls in Rust" diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index 6ede90112083..8bd859c97ada 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.55" +version = "0.1.56" authors = ["The Rust Clippy Developers"] edition = "2018" publish = false