From b24d75313ebda42104cf60977d03748976da8c40 Mon Sep 17 00:00:00 2001 From: Daniel Wagner-Hall Date: Sun, 17 Jun 2018 22:58:08 +0100 Subject: [PATCH] Exclude generated code --- clippy_lints/src/default_trait_access.rs | 23 +++++---- clippy_lints/src/utils/mod.rs | 14 ++++++ tests/ui/default_trait_access.rs | 63 +++++++++++++++++++++++- tests/ui/default_trait_access.stderr | 28 +++++++++-- 4 files changed, 113 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 0222f896e28..d96ed8db786 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -1,7 +1,8 @@ use rustc::hir::*; use rustc::lint::*; +use rustc::ty::TypeVariants; -use crate::utils::{match_def_path, opt_def_id, paths, span_lint_and_sugg}; +use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg}; /// **What it does:** Checks for literal calls to `Default::default()`. @@ -38,6 +39,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if_chain! { if let ExprCall(ref path, ..) = expr.node; + if !any_parent_is_automatically_derived(cx.tcx, expr.id); if let ExprPath(ref qpath) = path.node; if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)); if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD); @@ -46,14 +48,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { QPath::Resolved(..) => { // TODO: Work out a way to put "whatever the imported way of referencing // this type in this file" rather than a fully-qualified type. - let replacement = format!("{}::default()", cx.tables.expr_ty(expr)); - span_lint_and_sugg( - cx, - DEFAULT_TRAIT_ACCESS, - expr.span, - &format!("Calling {} is more clear than this expression", replacement), - "try", - replacement); + let expr_ty = cx.tables.expr_ty(expr); + if let TypeVariants::TyAdt(..) = expr_ty.sty { + let replacement = format!("{}::default()", expr_ty); + span_lint_and_sugg( + cx, + DEFAULT_TRAIT_ACCESS, + expr.span, + &format!("Calling {} is more clear than this expression", replacement), + "try", + replacement); + } }, QPath::TypeRelative(..) => {}, } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 6c3f0c25a3e..fd82b2b44d9 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1128,3 +1128,17 @@ pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> { without } + +pub fn any_parent_is_automatically_derived(tcx: TyCtxt, node: NodeId) -> bool { + let map = &tcx.hir; + let mut prev_enclosing_node = None; + let mut enclosing_node = node; + while Some(enclosing_node) != prev_enclosing_node { + if is_automatically_derived(map.attrs(enclosing_node)) { + return true; + } + prev_enclosing_node = Some(enclosing_node); + enclosing_node = map.get_parent(enclosing_node); + } + false +} diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index 9db875ee305..675e64246fa 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -23,7 +23,45 @@ fn main() { let s9: String = DefaultFactory::make_t_nicely(); - println!("[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}]", s1, s2, s3, s4, s5, s6, s7, s8, s9); + let s10 = DerivedDefault::default(); + + let s11: GenericDerivedDefault = Default::default(); + + let s12 = GenericDerivedDefault::::default(); + + let s13 = TupleDerivedDefault::default(); + + let s14: TupleDerivedDefault = Default::default(); + + let s15: ArrayDerivedDefault = Default::default(); + + let s16 = ArrayDerivedDefault::default(); + + let s17: TupleStructDerivedDefault = Default::default(); + + let s18 = TupleStructDerivedDefault::default(); + + println!( + "[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}]", + s1, + s2, + s3, + s4, + s5, + s6, + s7, + s8, + s9, + s10, + s11, + s12, + s13, + s14, + s15, + s16, + s17, + s18, + ); } struct DefaultFactory; @@ -37,3 +75,26 @@ impl DefaultFactory { T::default() } } + +#[derive(Debug, Default)] +struct DerivedDefault { + pub s: String, +} + +#[derive(Debug, Default)] +struct GenericDerivedDefault { + pub s: T, +} + +#[derive(Debug, Default)] +struct TupleDerivedDefault { + pub s: (String, String), +} + +#[derive(Debug, Default)] +struct ArrayDerivedDefault { + pub s: [String; 10], +} + +#[derive(Debug, Default)] +struct TupleStructDerivedDefault(String); diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr index b2cb49e6c80..8bb4731035a 100644 --- a/tests/ui/default_trait_access.stderr +++ b/tests/ui/default_trait_access.stderr @@ -24,11 +24,29 @@ error: Calling std::string::String::default() is more clear than this expression 18 | let s6: String = default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` -error: Calling T::default() is more clear than this expression - --> $DIR/default_trait_access.rs:33:9 +error: Calling GenericDerivedDefault::default() is more clear than this expression + --> $DIR/default_trait_access.rs:28:46 | -33 | Default::default() - | ^^^^^^^^^^^^^^^^^^ help: try: `T::default()` +28 | let s11: GenericDerivedDefault = Default::default(); + | ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault::default()` -error: aborting due to 5 previous errors +error: Calling TupleDerivedDefault::default() is more clear than this expression + --> $DIR/default_trait_access.rs:34:36 + | +34 | let s14: TupleDerivedDefault = Default::default(); + | ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()` + +error: Calling ArrayDerivedDefault::default() is more clear than this expression + --> $DIR/default_trait_access.rs:36:36 + | +36 | let s15: ArrayDerivedDefault = Default::default(); + | ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()` + +error: Calling TupleStructDerivedDefault::default() is more clear than this expression + --> $DIR/default_trait_access.rs:40:42 + | +40 | let s17: TupleStructDerivedDefault = Default::default(); + | ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()` + +error: aborting due to 8 previous errors