@@ -135,79 +135,86 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
135135 if impl_item. span . in_external_macro ( cx. sess ( ) . source_map ( ) ) {
136136 return ;
137137 }
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) ;
153182 }
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 ( )
160189 {
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+ } ;
180194
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) ;
193206 }
194- }
195-
196- if default_type. is_none ( ) {
207+ } ,
208+ Some ( DefaultType :: Manual ) => {
209+ // both `new` and `default` are manually implemented
210+ } ,
211+ None => {
197212 // there are no `Default` implementations for this type
198213 if !cx. effective_visibilities . is_reachable ( impl_item. owner_id . def_id ) {
199214 return ;
200215 }
201216 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+ } ,
211218 }
212219 }
213220 }
0 commit comments