@@ -3255,65 +3255,59 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
3255
3255
let self_ty = cx. tcx . type_of ( item. def_id ) ;
3256
3256
3257
3257
let implements_trait = matches ! ( item. kind, hir:: ItemKind :: Impl ( hir:: Impl { of_trait: Some ( _) , .. } ) ) ;
3258
- if_chain ! {
3259
- if let hir:: ImplItemKind :: Fn ( ref sig, id) = impl_item. kind;
3260
- if let Some ( first_arg) = iter_input_pats( sig. decl, cx. tcx. hir( ) . body( id) ) . next( ) ;
3261
-
3258
+ if let hir:: ImplItemKind :: Fn ( ref sig, id) = impl_item. kind {
3262
3259
let method_sig = cx. tcx . fn_sig ( impl_item. def_id ) ;
3263
3260
let method_sig = cx. tcx . erase_late_bound_regions ( method_sig) ;
3264
-
3265
- let first_arg_ty = method_sig. inputs( ) . iter( ) . next( ) ;
3266
-
3267
- // check conventions w.r.t. conversion method names and predicates
3268
- if let Some ( first_arg_ty) = first_arg_ty;
3269
-
3270
- then {
3271
- // if this impl block implements a trait, lint in trait definition instead
3272
- if !implements_trait && cx. access_levels. is_exported( impl_item. def_id) {
3273
- // check missing trait implementations
3274
- for method_config in & TRAIT_METHODS {
3275
- if name == method_config. method_name &&
3276
- sig. decl. inputs. len( ) == method_config. param_count &&
3277
- method_config. output_type. matches( & sig. decl. output) &&
3278
- method_config. self_kind. matches( cx, self_ty, * first_arg_ty) &&
3279
- fn_header_equals( method_config. fn_header, sig. header) &&
3280
- method_config. lifetime_param_cond( impl_item)
3281
- {
3282
- span_lint_and_help(
3283
- cx,
3284
- SHOULD_IMPLEMENT_TRAIT ,
3285
- impl_item. span,
3286
- & format!(
3287
- "method `{}` can be confused for the standard trait method `{}::{}`" ,
3288
- method_config. method_name,
3289
- method_config. trait_name,
3290
- method_config. method_name
3291
- ) ,
3292
- None ,
3293
- & format!(
3294
- "consider implementing the trait `{}` or choosing a less ambiguous method name" ,
3295
- method_config. trait_name
3296
- )
3297
- ) ;
3298
- }
3261
+ let first_arg_ty_opt = method_sig. inputs ( ) . iter ( ) . next ( ) . copied ( ) ;
3262
+ // if this impl block implements a trait, lint in trait definition instead
3263
+ if !implements_trait && cx. access_levels . is_exported ( impl_item. def_id ) {
3264
+ // check missing trait implementations
3265
+ for method_config in & TRAIT_METHODS {
3266
+ if name == method_config. method_name
3267
+ && sig. decl . inputs . len ( ) == method_config. param_count
3268
+ && method_config. output_type . matches ( & sig. decl . output )
3269
+ // in case there is no first arg, since we already have checked the number of arguments
3270
+ // it's should be always true
3271
+ && first_arg_ty_opt. map_or ( true , |first_arg_ty| method_config
3272
+ . self_kind . matches ( cx, self_ty, first_arg_ty)
3273
+ )
3274
+ && fn_header_equals ( method_config. fn_header , sig. header )
3275
+ && method_config. lifetime_param_cond ( impl_item)
3276
+ {
3277
+ span_lint_and_help (
3278
+ cx,
3279
+ SHOULD_IMPLEMENT_TRAIT ,
3280
+ impl_item. span ,
3281
+ & format ! (
3282
+ "method `{}` can be confused for the standard trait method `{}::{}`" ,
3283
+ method_config. method_name, method_config. trait_name, method_config. method_name
3284
+ ) ,
3285
+ None ,
3286
+ & format ! (
3287
+ "consider implementing the trait `{}` or choosing a less ambiguous method name" ,
3288
+ method_config. trait_name
3289
+ ) ,
3290
+ ) ;
3299
3291
}
3300
3292
}
3293
+ }
3301
3294
3302
- if sig. decl. implicit_self. has_implicit_self( )
3295
+ if sig. decl . implicit_self . has_implicit_self ( )
3303
3296
&& !( self . avoid_breaking_exported_api
3304
- && cx. access_levels. is_exported( impl_item. def_id) )
3297
+ && cx. access_levels . is_exported ( impl_item. def_id ) )
3298
+ && let Some ( first_arg) = iter_input_pats ( sig. decl , cx. tcx . hir ( ) . body ( id) ) . next ( )
3299
+ && let Some ( first_arg_ty) = first_arg_ty_opt
3305
3300
{
3306
3301
wrong_self_convention:: check (
3307
3302
cx,
3308
3303
name,
3309
3304
self_ty,
3310
- * first_arg_ty,
3305
+ first_arg_ty,
3311
3306
first_arg. pat . span ,
3312
3307
implements_trait,
3313
3308
false
3314
3309
) ;
3315
3310
}
3316
- }
3317
3311
}
3318
3312
3319
3313
// if this impl block implements a trait, lint in trait definition instead
@@ -3799,7 +3793,6 @@ const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [
3799
3793
ShouldImplTraitCase :: new ( "std::borrow::BorrowMut" , "borrow_mut" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
3800
3794
ShouldImplTraitCase :: new ( "std::clone::Clone" , "clone" , 1 , FN_HEADER , SelfKind :: Ref , OutType :: Any , true ) ,
3801
3795
ShouldImplTraitCase :: new ( "std::cmp::Ord" , "cmp" , 2 , FN_HEADER , SelfKind :: Ref , OutType :: Any , true ) ,
3802
- // FIXME: default doesn't work
3803
3796
ShouldImplTraitCase :: new ( "std::default::Default" , "default" , 0 , FN_HEADER , SelfKind :: No , OutType :: Any , true ) ,
3804
3797
ShouldImplTraitCase :: new ( "std::ops::Deref" , "deref" , 1 , FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
3805
3798
ShouldImplTraitCase :: new ( "std::ops::DerefMut" , "deref_mut" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
@@ -3827,7 +3820,7 @@ enum SelfKind {
3827
3820
Value ,
3828
3821
Ref ,
3829
3822
RefMut ,
3830
- No ,
3823
+ No , // When we want the first argument type to be different than `Self`
3831
3824
}
3832
3825
3833
3826
impl SelfKind {
0 commit comments