@@ -135,79 +135,86 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
135
135
if impl_item. span . in_external_macro ( cx. sess ( ) . source_map ( ) ) {
136
136
return ;
137
137
}
138
- if let hir:: ImplItemKind :: Fn ( ref sig, body_id) = impl_item. kind {
139
- let name = impl_item. ident . name ;
140
- let id = impl_item. owner_id ;
141
- if sig. header . is_unsafe ( ) {
142
- // can't be implemented for unsafe new
143
- return ;
144
- }
145
- if cx. tcx . is_doc_hidden ( impl_item. owner_id . def_id ) {
146
- // shouldn't be implemented when it is hidden in docs
147
- return ;
148
- }
149
- if !impl_item. generics . params . is_empty ( ) {
150
- // when the result of `new()` depends on a parameter we should not require
151
- // an impl of `Default`
152
- return ;
138
+ let hir:: ImplItemKind :: Fn ( ref sig, body_id) = impl_item. kind else {
139
+ continue ;
140
+ } ;
141
+
142
+ let name = impl_item. ident . name ;
143
+ let id = impl_item. owner_id ;
144
+ if sig. header . is_unsafe ( ) {
145
+ // can't be implemented for unsafe new
146
+ return ;
147
+ }
148
+ if cx. tcx . is_doc_hidden ( impl_item. owner_id . def_id ) {
149
+ // shouldn't be implemented when it is hidden in docs
150
+ return ;
151
+ }
152
+ if !impl_item. generics . params . is_empty ( ) {
153
+ // when the result of `new()` depends on a parameter we should not require
154
+ // an impl of `Default`
155
+ return ;
156
+ }
157
+ if sig. decl . inputs . is_empty ( )
158
+ && name == sym:: new
159
+ && let self_def_id = cx. tcx . hir ( ) . get_parent_item ( id. into ( ) )
160
+ && let self_ty = cx. tcx . type_of ( self_def_id) . instantiate_identity ( )
161
+ && self_ty == return_ty ( cx, id)
162
+ && let Some ( default_trait_id) = cx. tcx . get_diagnostic_item ( sym:: Default )
163
+ {
164
+ if self . impling_types . is_none ( ) {
165
+ let mut impls = HirIdMap :: default ( ) ;
166
+ cx. tcx . for_each_impl ( default_trait_id, |d| {
167
+ let ty = cx. tcx . type_of ( d) . instantiate_identity ( ) ;
168
+ if let Some ( ty_def) = ty. ty_adt_def ( ) {
169
+ if let Some ( local_def_id) = ty_def. did ( ) . as_local ( ) {
170
+ impls. insert (
171
+ cx. tcx . local_def_id_to_hir_id ( local_def_id) ,
172
+ if cx. tcx . is_builtin_derived ( d) {
173
+ DefaultType :: AutoDerived
174
+ } else {
175
+ DefaultType :: Manual
176
+ } ,
177
+ ) ;
178
+ }
179
+ }
180
+ } ) ;
181
+ self . impling_types = Some ( impls) ;
153
182
}
154
- if sig . decl . inputs . is_empty ( )
155
- && name == sym :: new
156
- && let self_def_id = cx . tcx . hir ( ) . get_parent_item ( id . into ( ) )
157
- && let self_ty = cx. tcx . type_of ( self_def_id) . instantiate_identity ( )
158
- && self_ty == return_ty ( cx , id )
159
- && let Some ( default_trait_id ) = cx . tcx . get_diagnostic_item ( sym :: Default )
183
+
184
+ // Check if a Default implementation exists for the Self type, regardless of generics
185
+ let default_type = if let Some ( ref impling_types ) = self . impling_types
186
+ && let self_def = cx. tcx . type_of ( self_def_id) . instantiate_identity ( )
187
+ && let Some ( self_def ) = self_def . ty_adt_def ( )
188
+ && let Some ( self_local_did ) = self_def . did ( ) . as_local ( )
160
189
{
161
- if self . impling_types . is_none ( ) {
162
- let mut impls = HirIdMap :: default ( ) ;
163
- cx. tcx . for_each_impl ( default_trait_id, |d| {
164
- let ty = cx. tcx . type_of ( d) . instantiate_identity ( ) ;
165
- if let Some ( ty_def) = ty. ty_adt_def ( ) {
166
- if let Some ( local_def_id) = ty_def. did ( ) . as_local ( ) {
167
- impls. insert (
168
- cx. tcx . local_def_id_to_hir_id ( local_def_id) ,
169
- if cx. tcx . is_builtin_derived ( d) {
170
- DefaultType :: AutoDerived
171
- } else {
172
- DefaultType :: Manual
173
- } ,
174
- ) ;
175
- }
176
- }
177
- } ) ;
178
- self . impling_types = Some ( impls) ;
179
- }
190
+ impling_types. get ( & cx. tcx . local_def_id_to_hir_id ( self_local_did) )
191
+ } else {
192
+ None
193
+ } ;
180
194
181
- let mut default_type = None ;
182
- // Check if a Default implementation exists for the Self type, regardless of generics
183
- if let Some ( ref impling_types) = self . impling_types
184
- && let self_def = cx. tcx . type_of ( self_def_id) . instantiate_identity ( )
185
- && let Some ( self_def) = self_def. ty_adt_def ( )
186
- && let Some ( self_local_did) = self_def. did ( ) . as_local ( )
187
- {
188
- let self_id = cx. tcx . local_def_id_to_hir_id ( self_local_did) ;
189
- default_type = impling_types. get ( & self_id) ;
190
- if let Some ( DefaultType :: Manual ) = default_type {
191
- // both `new` and `default` are manually implemented
192
- return ;
195
+ match default_type {
196
+ Some ( DefaultType :: AutoDerived ) => {
197
+ if let hir:: ExprKind :: Block ( block, _) = cx. tcx . hir_body ( body_id) . value . kind
198
+ && !is_unit_struct ( cx, self_ty)
199
+ // TODO: handle generics
200
+ && generics. params . is_empty ( )
201
+ // this type has an automatically derived `Default` implementation
202
+ // check if `new` and `default` are equivalent
203
+ && let Some ( span) = check_block_calls_default ( cx, block)
204
+ {
205
+ suggest_default_mismatch_new ( cx, span, id, block, self_ty, impl_self_ty) ;
193
206
}
194
- }
195
-
196
- if default_type. is_none ( ) {
207
+ } ,
208
+ Some ( DefaultType :: Manual ) => {
209
+ // both `new` and `default` are manually implemented
210
+ } ,
211
+ None => {
197
212
// there are no `Default` implementations for this type
198
213
if !cx. effective_visibilities . is_reachable ( impl_item. owner_id . def_id ) {
199
214
return ;
200
215
}
201
216
suggest_new_without_default ( cx, item, impl_item, id, self_ty, generics, impl_self_ty) ;
202
- } else if let hir:: ExprKind :: Block ( block, _) = cx. tcx . hir_body ( body_id) . value . kind
203
- && !is_unit_struct ( cx, self_ty)
204
- // TODO: handle generics
205
- && generics. params . is_empty ( )
206
- // check if `new` and `default` are equivalent
207
- && let Some ( span) = check_block_calls_default ( cx, block)
208
- {
209
- suggest_default_mismatch_new ( cx, span, id, block, self_ty, impl_self_ty) ;
210
- }
217
+ } ,
211
218
}
212
219
}
213
220
}
0 commit comments