@@ -1496,26 +1496,21 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1496
1496
1497
1497
then {
1498
1498
if cx. access_levels. is_exported( impl_item. hir_id) {
1499
- // check missing trait implementations
1500
- for & ( method_name, n_args, fn_header, self_kind, out_type, trait_name) in & TRAIT_METHODS {
1501
- let no_lifetime_params = || {
1502
- !impl_item. generics. params. iter( )
1503
- . any( |p| matches!(
1504
- p. kind,
1505
- hir:: GenericParamKind :: Lifetime { kind: hir:: LifetimeParamKind :: Explicit } ) )
1506
- } ;
1507
- if name == method_name &&
1508
- sig. decl. inputs. len( ) == n_args &&
1509
- out_type. matches( cx, & sig. decl. output) &&
1510
- self_kind. matches( cx, self_ty, first_arg_ty) &&
1511
- fn_header_equals( * fn_header, sig. header) &&
1512
- // ignore methods with lifetime params, risk of false positive
1513
- no_lifetime_params( )
1499
+ // check missing trait implementations
1500
+ for method_config in & TRAIT_METHODS {
1501
+ if name == method_config. method_name &&
1502
+ sig. decl. inputs. len( ) == method_config. param_count &&
1503
+ method_config. output_type. matches( cx, & sig. decl. output) &&
1504
+ method_config. self_kind. matches( cx, self_ty, first_arg_ty) &&
1505
+ fn_header_equals( * method_config. fn_header, sig. header) &&
1506
+ method_config. lifetime_param_cond( & impl_item)
1514
1507
{
1515
1508
span_lint( cx, SHOULD_IMPLEMENT_TRAIT , impl_item. span, & format!(
1516
1509
"defining a method called `{}` on this type; consider implementing \
1517
- the `{}` trait or choosing a less ambiguous name", name, trait_name) ) ;
1510
+ the `{}` trait or choosing a less ambiguous name",
1511
+ method_config. method_name, method_config. trait_name) ) ;
1518
1512
}
1513
+
1519
1514
}
1520
1515
}
1521
1516
@@ -3398,39 +3393,85 @@ const FN_HEADER: hir::FnHeader = hir::FnHeader {
3398
3393
abi : rustc_target:: spec:: abi:: Abi :: Rust ,
3399
3394
} ;
3400
3395
3396
+ struct ShouldNotImplCase {
3397
+ trait_name : & ' static str ,
3398
+ method_name : & ' static str ,
3399
+ param_count : usize ,
3400
+ fn_header : & ' static hir:: FnHeader ,
3401
+ // implicit self kind expected (none, self, &self, ...)
3402
+ self_kind : SelfKind ,
3403
+ // checks against the output type
3404
+ output_type : OutType ,
3405
+ // certain methods with explicit lifetimes can't implement the equivalent trait method
3406
+ lint_explicit_lifetime : bool ,
3407
+ }
3408
+ impl ShouldNotImplCase {
3409
+ const fn new (
3410
+ trait_name : & ' static str ,
3411
+ method_name : & ' static str ,
3412
+ param_count : usize ,
3413
+ fn_header : & ' static hir:: FnHeader ,
3414
+ self_kind : SelfKind ,
3415
+ output_type : OutType ,
3416
+ lint_explicit_lifetime : bool ,
3417
+ ) -> ShouldNotImplCase {
3418
+ ShouldNotImplCase {
3419
+ trait_name,
3420
+ method_name,
3421
+ param_count,
3422
+ fn_header,
3423
+ self_kind,
3424
+ output_type,
3425
+ lint_explicit_lifetime,
3426
+ }
3427
+ }
3428
+
3429
+ fn lifetime_param_cond ( & self , impl_item : & hir:: ImplItem < ' _ > ) -> bool {
3430
+ self . lint_explicit_lifetime
3431
+ || !impl_item. generics . params . iter ( ) . any ( |p| {
3432
+ matches ! (
3433
+ p. kind,
3434
+ hir:: GenericParamKind :: Lifetime {
3435
+ kind: hir:: LifetimeParamKind :: Explicit
3436
+ }
3437
+ )
3438
+ } )
3439
+ }
3440
+ }
3441
+
3401
3442
#[ rustfmt:: skip]
3402
- const TRAIT_METHODS : [ ( & str , usize , & hir :: FnHeader , SelfKind , OutType , & str ) ; 30 ] = [
3403
- ( " add", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , "std::ops::Add" ) ,
3404
- ( " as_mut", 1 , & FN_HEADER , SelfKind :: RefMut , OutType :: Ref , "std::convert::AsMut" ) ,
3405
- ( " as_ref", 1 , & FN_HEADER , SelfKind :: Ref , OutType :: Ref , "std::convert::AsRef" ) ,
3406
- ( " bitand", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , "std::ops::BitAnd" ) ,
3407
- ( " bitor", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , "std::ops::BitOr" ) ,
3408
- ( " bitxor", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , "std::ops::BitXor" ) ,
3409
- ( " borrow", 1 , & FN_HEADER , SelfKind :: Ref , OutType :: Ref , "std::borrow::Borrow" ) ,
3410
- ( " borrow_mut", 1 , & FN_HEADER , SelfKind :: RefMut , OutType :: Ref , "std::borrow::BorrowMut" ) ,
3411
- ( " clone", 1 , & FN_HEADER , SelfKind :: Ref , OutType :: Any , "std::clone::Clone" ) ,
3412
- ( " cmp", 2 , & FN_HEADER , SelfKind :: Ref , OutType :: Any , "std::cmp::Ord" ) ,
3443
+ const TRAIT_METHODS : [ ShouldNotImplCase ; 30 ] = [
3444
+ ShouldNotImplCase :: new ( "std::ops::Add" , " add", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
3445
+ ShouldNotImplCase :: new ( "std::convert::AsMut" , " as_mut", 1 , & FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
3446
+ ShouldNotImplCase :: new ( "std::convert::AsRef" , " as_ref", 1 , & FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
3447
+ ShouldNotImplCase :: new ( "std::ops::BitAnd" , " bitand", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
3448
+ ShouldNotImplCase :: new ( "std::ops::BitOr" , " bitor", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
3449
+ ShouldNotImplCase :: new ( "std::ops::BitXor" , " bitxor", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
3450
+ ShouldNotImplCase :: new ( "std:: borrow::Borrow ", "borrow" , 1 , & FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
3451
+ ShouldNotImplCase :: new ( "std::borrow::BorrowMut" , " borrow_mut", 1 , & FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
3452
+ ShouldNotImplCase :: new ( "std:: clone::Clone ", "clone" , 1 , & FN_HEADER , SelfKind :: Ref , OutType :: Any , true ) ,
3453
+ ShouldNotImplCase :: new ( "std:: cmp::Ord ", "cmp" , 2 , & FN_HEADER , SelfKind :: Ref , OutType :: Any , true ) ,
3413
3454
// FIXME: default doesn't work
3414
- ( " default", 0 , & FN_HEADER , SelfKind :: No , OutType :: Any , "std::default::Default" ) ,
3415
- ( " deref", 1 , & FN_HEADER , SelfKind :: Ref , OutType :: Ref , "std::ops::Deref" ) ,
3416
- ( " deref_mut", 1 , & FN_HEADER , SelfKind :: RefMut , OutType :: Ref , "std::ops::DerefMut" ) ,
3417
- ( " div", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , "std::ops::Div" ) ,
3418
- ( " drop", 1 , & FN_HEADER , SelfKind :: RefMut , OutType :: Unit , "std::ops::Drop" ) ,
3419
- ( " eq", 2 , & FN_HEADER , SelfKind :: Ref , OutType :: Bool , "std::cmp::PartialEq" ) ,
3420
- ( " from_iter", 1 , & FN_HEADER , SelfKind :: No , OutType :: Any , "std::iter::FromIterator" ) ,
3421
- ( " from_str", 1 , & FN_HEADER , SelfKind :: No , OutType :: Any , "std::str::FromStr" ) ,
3422
- ( " hash", 2 , & FN_HEADER , SelfKind :: Ref , OutType :: Unit , "std::hash::Hash" ) ,
3423
- ( " index", 2 , & FN_HEADER , SelfKind :: Ref , OutType :: Ref , "std::ops::Index" ) ,
3424
- ( " index_mut", 2 , & FN_HEADER , SelfKind :: RefMut , OutType :: Ref , "std::ops::IndexMut" ) ,
3425
- ( " into_iter", 1 , & FN_HEADER , SelfKind :: Value , OutType :: Any , "std::iter::IntoIterator" ) ,
3426
- ( " mul", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , "std::ops::Mul" ) ,
3427
- ( " neg", 1 , & FN_HEADER , SelfKind :: Value , OutType :: Any , "std::ops::Neg" ) ,
3428
- ( " next", 1 , & FN_HEADER , SelfKind :: RefMut , OutType :: Any , "std::iter::Iterator" ) ,
3429
- ( " not", 1 , & FN_HEADER , SelfKind :: Value , OutType :: Any , "std::ops::Not" ) ,
3430
- ( " rem", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , "std::ops::Rem" ) ,
3431
- ( " shl", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , "std::ops::Shl" ) ,
3432
- ( " shr", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , "std::ops::Shr" ) ,
3433
- ( " sub", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , "std::ops::Sub" ) ,
3455
+ ShouldNotImplCase :: new ( "std:: default::Default ", "default" , 0 , & FN_HEADER , SelfKind :: No , OutType :: Any , true ) ,
3456
+ ShouldNotImplCase :: new ( "std::ops::Deref" , " deref", 1 , & FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
3457
+ ShouldNotImplCase :: new ( "std::ops::DerefMut" , " deref_mut", 1 , & FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
3458
+ ShouldNotImplCase :: new ( "std::ops::Div" , " div", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
3459
+ ShouldNotImplCase :: new ( "std::ops::Drop" , " drop", 1 , & FN_HEADER , SelfKind :: RefMut , OutType :: Unit , true ) ,
3460
+ ShouldNotImplCase :: new ( "std::cmp::PartialEq" , " eq", 2 , & FN_HEADER , SelfKind :: Ref , OutType :: Bool , true ) ,
3461
+ ShouldNotImplCase :: new ( "std::iter::FromIterator" , " from_iter", 1 , & FN_HEADER , SelfKind :: No , OutType :: Any , true ) ,
3462
+ ShouldNotImplCase :: new ( "std::str::FromStr" , " from_str", 1 , & FN_HEADER , SelfKind :: No , OutType :: Any , true ) ,
3463
+ ShouldNotImplCase :: new ( "std:: hash::Hash ", "hash" , 2 , & FN_HEADER , SelfKind :: Ref , OutType :: Unit , true ) ,
3464
+ ShouldNotImplCase :: new ( "std::ops::Index" , " index", 2 , & FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
3465
+ ShouldNotImplCase :: new ( "std::ops::IndexMut" , " index_mut", 2 , & FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
3466
+ ShouldNotImplCase :: new ( "std::iter::IntoIterator" , " into_iter", 1 , & FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
3467
+ ShouldNotImplCase :: new ( "std::ops::Mul" , " mul", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
3468
+ ShouldNotImplCase :: new ( "std::ops::Neg" , " neg", 1 , & FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
3469
+ ShouldNotImplCase :: new ( "std::iter::Iterator" , " next", 1 , & FN_HEADER , SelfKind :: RefMut , OutType :: Any , false ) ,
3470
+ ShouldNotImplCase :: new ( "std::ops::Not" , " not", 1 , & FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
3471
+ ShouldNotImplCase :: new ( "std::ops::Rem" , " rem", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
3472
+ ShouldNotImplCase :: new ( "std::ops::Shl" , " shl", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
3473
+ ShouldNotImplCase :: new ( "std::ops::Shr" , " shr", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
3474
+ ShouldNotImplCase :: new ( "std::ops::Sub" , " sub", 2 , & FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
3434
3475
] ;
3435
3476
3436
3477
#[ rustfmt:: skip]
0 commit comments