@@ -3255,65 +3255,59 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
32553255 let self_ty = cx. tcx . type_of ( item. def_id ) ;
32563256
32573257 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 {
32623259 let method_sig = cx. tcx . fn_sig ( impl_item. def_id ) ;
32633260 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+ ) ;
32993291 }
33003292 }
3293+ }
33013294
3302- if sig. decl. implicit_self. has_implicit_self( )
3295+ if sig. decl . implicit_self . has_implicit_self ( )
33033296 && !( 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
33053300 {
33063301 wrong_self_convention:: check (
33073302 cx,
33083303 name,
33093304 self_ty,
3310- * first_arg_ty,
3305+ first_arg_ty,
33113306 first_arg. pat . span ,
33123307 implements_trait,
33133308 false
33143309 ) ;
33153310 }
3316- }
33173311 }
33183312
33193313 // if this impl block implements a trait, lint in trait definition instead
@@ -3799,7 +3793,6 @@ const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [
37993793 ShouldImplTraitCase :: new ( "std::borrow::BorrowMut" , "borrow_mut" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
38003794 ShouldImplTraitCase :: new ( "std::clone::Clone" , "clone" , 1 , FN_HEADER , SelfKind :: Ref , OutType :: Any , true ) ,
38013795 ShouldImplTraitCase :: new ( "std::cmp::Ord" , "cmp" , 2 , FN_HEADER , SelfKind :: Ref , OutType :: Any , true ) ,
3802- // FIXME: default doesn't work
38033796 ShouldImplTraitCase :: new ( "std::default::Default" , "default" , 0 , FN_HEADER , SelfKind :: No , OutType :: Any , true ) ,
38043797 ShouldImplTraitCase :: new ( "std::ops::Deref" , "deref" , 1 , FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
38053798 ShouldImplTraitCase :: new ( "std::ops::DerefMut" , "deref_mut" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
@@ -3827,7 +3820,7 @@ enum SelfKind {
38273820 Value ,
38283821 Ref ,
38293822 RefMut ,
3830- No ,
3823+ No , // When we want the first argument type to be different than `Self`
38313824}
38323825
38333826impl SelfKind {
0 commit comments