| 
11 | 11 | use crate::rustc::hir::def_id::DefId;  | 
12 | 12 | use crate::rustc::hir;  | 
13 | 13 | use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext};  | 
 | 14 | +use crate::rustc::util::nodemap::NodeSet;  | 
14 | 15 | use crate::rustc::{declare_tool_lint, lint_array};  | 
15 | 16 | use if_chain::if_chain;  | 
16 | 17 | use crate::rustc::ty::{self, Ty};  | 
@@ -91,8 +92,10 @@ declare_clippy_lint! {  | 
91 | 92 |     "`fn new() -> Self` without `#[derive]`able `Default` implementation"  | 
92 | 93 | }  | 
93 | 94 | 
 
  | 
94 |  | -#[derive(Copy, Clone)]  | 
95 |  | -pub struct NewWithoutDefault;  | 
 | 95 | +#[derive(Clone, Default)]  | 
 | 96 | +pub struct NewWithoutDefault {  | 
 | 97 | +    impling_types: Option<NodeSet>,  | 
 | 98 | +}  | 
96 | 99 | 
 
  | 
97 | 100 | impl LintPass for NewWithoutDefault {  | 
98 | 101 |     fn get_lints(&self) -> LintArray {  | 
@@ -130,13 +133,39 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {  | 
130 | 133 |                             return;  | 
131 | 134 |                         }  | 
132 | 135 |                         if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) {  | 
 | 136 | +                            let self_did = cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id));  | 
133 | 137 |                             let self_ty = cx.tcx  | 
134 |  | -                                .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)));  | 
 | 138 | +                                .type_of(self_did);  | 
135 | 139 |                             if_chain! {  | 
136 | 140 |                                 if same_tys(cx, self_ty, return_ty(cx, id));  | 
137 | 141 |                                 if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);  | 
138 |  | -                                if !implements_trait(cx, self_ty, default_trait_id, &[]);  | 
139 | 142 |                                 then {  | 
 | 143 | +                                    if self.impling_types.is_none() {  | 
 | 144 | +                                        let mut impls = NodeSet();  | 
 | 145 | +                                        cx.tcx.for_each_impl(default_trait_id, |d| {  | 
 | 146 | +                                            if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {  | 
 | 147 | +                                                if let Some(node_id) = cx.tcx.hir.as_local_node_id(ty_def.did) {  | 
 | 148 | +                                                    impls.insert(node_id);  | 
 | 149 | +                                                }  | 
 | 150 | +                                            }  | 
 | 151 | +                                        });  | 
 | 152 | +                                        self.impling_types = Some(impls);  | 
 | 153 | +                                    }  | 
 | 154 | + | 
 | 155 | +                                    // Check if a Default implementation exists for the Self type, regardless of  | 
 | 156 | +                                    // generics  | 
 | 157 | +                                    if_chain! {  | 
 | 158 | +                                        if let Some(ref impling_types) = self.impling_types;  | 
 | 159 | +                                        if let Some(self_def) = cx.tcx.type_of(self_did).ty_adt_def();  | 
 | 160 | +                                        if self_def.did.is_local();  | 
 | 161 | +                                        then {  | 
 | 162 | +                                            let self_id = cx.tcx.hir.local_def_id_to_node_id(self_def.did.to_local());  | 
 | 163 | +                                            if impling_types.contains(&self_id) {  | 
 | 164 | +                                                return;  | 
 | 165 | +                                            }  | 
 | 166 | +                                        }  | 
 | 167 | +                                    }  | 
 | 168 | + | 
140 | 169 |                                     if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {  | 
141 | 170 |                                         span_lint_and_then(  | 
142 | 171 |                                             cx,  | 
 | 
0 commit comments