1
1
use crate :: utils:: paths;
2
2
use crate :: utils:: sugg:: DiagnosticBuilderExt ;
3
- use crate :: utils:: { get_trait_def_id, implements_trait , return_ty, same_tys, span_lint_hir_and_then} ;
3
+ use crate :: utils:: { get_trait_def_id, return_ty, same_tys, span_lint_hir_and_then} ;
4
4
use if_chain:: if_chain;
5
5
use rustc_errors:: Applicability ;
6
6
use rustc_hir as hir;
7
- use rustc_hir:: def_id:: DefId ;
8
7
use rustc_hir:: HirIdSet ;
9
8
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
10
9
use rustc_middle:: lint:: in_external_macro;
11
- use rustc_middle:: ty:: { self , Ty } ;
10
+ use rustc_middle:: ty:: Ty ;
12
11
use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
13
- use rustc_span:: source_map:: Span ;
14
12
15
13
declare_clippy_lint ! {
16
14
/// **What it does:** Checks for types with a `fn new() -> Self` method and no
17
15
/// implementation of
18
16
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html).
19
17
///
20
- /// It detects both the case when a manual
21
- /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)
22
- /// implementation is required and also when it can be created with
23
- /// `#[derive(Default)]`
24
- ///
25
18
/// **Why is this bad?** The user might expect to be able to use
26
19
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the
27
20
/// type can be constructed without arguments.
@@ -40,46 +33,17 @@ declare_clippy_lint! {
40
33
/// }
41
34
/// ```
42
35
///
43
- /// Instead, use :
36
+ /// To fix the lint, and a `Default` implementation that delegates to `new` :
44
37
///
45
38
/// ```ignore
46
39
/// struct Foo(Bar);
47
40
///
48
41
/// impl Default for Foo {
49
42
/// fn default() -> Self {
50
- /// Foo(Bar ::new() )
43
+ /// Foo::new()
51
44
/// }
52
45
/// }
53
46
/// ```
54
- ///
55
- /// Or, if
56
- /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)
57
- /// can be derived by `#[derive(Default)]`:
58
- ///
59
- /// ```rust
60
- /// struct Foo;
61
- ///
62
- /// impl Foo {
63
- /// fn new() -> Self {
64
- /// Foo
65
- /// }
66
- /// }
67
- /// ```
68
- ///
69
- /// Instead, use:
70
- ///
71
- /// ```rust
72
- /// #[derive(Default)]
73
- /// struct Foo;
74
- ///
75
- /// impl Foo {
76
- /// fn new() -> Self {
77
- /// Foo
78
- /// }
79
- /// }
80
- /// ```
81
- ///
82
- /// You can also have `new()` call `Default::default()`.
83
47
pub NEW_WITHOUT_DEFAULT ,
84
48
style,
85
49
"`fn new() -> Self` method without `Default` implementation"
@@ -158,46 +122,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
158
122
}
159
123
}
160
124
161
- if let Some ( sp) = can_derive_default( self_ty, cx, default_trait_id) {
162
- span_lint_hir_and_then(
163
- cx,
164
- NEW_WITHOUT_DEFAULT ,
165
- id,
166
- impl_item. span,
167
- & format!(
168
- "you should consider deriving a `Default` implementation for `{}`" ,
169
- self_ty
170
- ) ,
171
- |diag| {
172
- diag. suggest_item_with_attr(
173
- cx,
174
- sp,
175
- "try this" ,
176
- "#[derive(Default)]" ,
177
- Applicability :: MaybeIncorrect ,
178
- ) ;
179
- } ) ;
180
- } else {
181
- span_lint_hir_and_then(
182
- cx,
183
- NEW_WITHOUT_DEFAULT ,
184
- id,
185
- impl_item. span,
186
- & format!(
187
- "you should consider adding a `Default` implementation for `{}`" ,
188
- self_ty
189
- ) ,
190
- |diag| {
191
- diag. suggest_prepend_item(
192
- cx,
193
- item. span,
194
- "try this" ,
195
- & create_new_without_default_suggest_msg( self_ty) ,
196
- Applicability :: MaybeIncorrect ,
197
- ) ;
198
- } ,
199
- ) ;
200
- }
125
+ span_lint_hir_and_then(
126
+ cx,
127
+ NEW_WITHOUT_DEFAULT ,
128
+ id,
129
+ impl_item. span,
130
+ & format!(
131
+ "you should consider adding a `Default` implementation for `{}`" ,
132
+ self_ty
133
+ ) ,
134
+ |diag| {
135
+ diag. suggest_prepend_item(
136
+ cx,
137
+ item. span,
138
+ "try this" ,
139
+ & create_new_without_default_suggest_msg( self_ty) ,
140
+ Applicability :: MaybeIncorrect ,
141
+ ) ;
142
+ } ,
143
+ ) ;
201
144
}
202
145
}
203
146
}
@@ -217,18 +160,3 @@ fn create_new_without_default_suggest_msg(ty: Ty<'_>) -> String {
217
160
}}
218
161
}}" , ty)
219
162
}
220
-
221
- fn can_derive_default < ' t , ' c > ( ty : Ty < ' t > , cx : & LateContext < ' c , ' t > , default_trait_id : DefId ) -> Option < Span > {
222
- match ty. kind {
223
- ty:: Adt ( adt_def, substs) if adt_def. is_struct ( ) => {
224
- for field in adt_def. all_fields ( ) {
225
- let f_ty = field. ty ( cx. tcx , substs) ;
226
- if !implements_trait ( cx, f_ty, default_trait_id, & [ ] ) {
227
- return None ;
228
- }
229
- }
230
- Some ( cx. tcx . def_span ( adt_def. did ) )
231
- } ,
232
- _ => None ,
233
- }
234
- }
0 commit comments