@@ -3173,56 +3173,76 @@ declare_lint_pass!(DuplicateBounds => [DUPLICATE_BOUNDS]);
31733173
31743174impl < ' tcx > LateLintPass < ' tcx > for DuplicateBounds {
31753175 fn check_generics ( & mut self , cx : & LateContext < ' tcx > , gen : & ' tcx hir:: Generics < ' _ > ) {
3176- struct TraitRes {
3177- res : Res ,
3176+ struct Bound {
3177+ kind : BoundKind ,
31783178 span : Span ,
31793179 }
31803180
3181- impl TraitRes {
3182- fn from_bound ( bound : & hir:: GenericBound < ' _ > ) -> Option < Self > {
3183- if let hir:: GenericBound :: Trait ( t, _) = bound {
3184- Some ( Self { res : t. trait_ref . path . res , span : t. span } )
3185- } else {
3186- None
3181+ #[ derive( Hash , PartialEq , Eq ) ]
3182+ enum BoundKind {
3183+ Trait ( Res ) ,
3184+ Lifetime ( hir:: LifetimeName ) ,
3185+ }
3186+
3187+ impl BoundKind {
3188+ fn as_str ( & self ) -> & ' static str {
3189+ match self {
3190+ BoundKind :: Trait ( _) => "trait" ,
3191+ BoundKind :: Lifetime ( _) => "lifetime" ,
3192+ }
3193+ }
3194+ }
3195+
3196+ impl Bound {
3197+ fn from_generic ( bound : & hir:: GenericBound < ' _ > ) -> Option < Self > {
3198+ match bound {
3199+ hir:: GenericBound :: Trait ( t, _) => {
3200+ Some ( Self { kind : BoundKind :: Trait ( t. trait_ref . path . res ) , span : t. span } )
3201+ }
3202+ hir:: GenericBound :: Outlives ( lifetime) => {
3203+ Some ( Self { kind : BoundKind :: Lifetime ( lifetime. name ) , span : lifetime. span } )
3204+ }
3205+ _ => None ,
31873206 }
31883207 }
31893208 }
31903209
3191- impl PartialEq for TraitRes {
3210+ impl PartialEq for Bound {
31923211 fn eq ( & self , other : & Self ) -> bool {
3193- self . res == other. res
3212+ self . kind == other. kind
31943213 }
31953214 }
31963215
3197- impl Hash for TraitRes {
3216+ impl Hash for Bound {
31983217 fn hash < H : Hasher > ( & self , state : & mut H ) {
3199- self . res . hash ( state)
3218+ self . kind . hash ( state)
32003219 }
32013220 }
32023221
3203- impl Eq for TraitRes { }
3222+ impl Eq for Bound { }
32043223
32053224 if gen. span . from_expansion ( ) {
32063225 return ;
32073226 }
32083227
3209- let mut trait_resolutions = FxHashMap :: default ( ) ;
3228+ let mut bounds = FxHashMap :: default ( ) ;
32103229 for param in gen. params {
32113230 if let hir:: ParamName :: Plain ( ref ident) = param. name {
3212- let mut uniq = FxHashSet :: default ( ) ;
3231+ let mut uniq_bounds = FxHashSet :: default ( ) ;
32133232
3214- for res in param. bounds . iter ( ) . filter_map ( TraitRes :: from_bound ) {
3233+ for res in param. bounds . iter ( ) . filter_map ( Bound :: from_generic ) {
32153234 let span = res. span . clone ( ) ;
3216- if !uniq. insert ( res) {
3235+ let kind = res. kind . as_str ( ) ;
3236+ if !uniq_bounds. insert ( res) {
32173237 cx. struct_span_lint ( DUPLICATE_BOUNDS , span, |lint| {
3218- lint. build ( "this trait bound has already been specified" )
3219- . help ( "consider removing this trait bound" )
3238+ lint. build ( & format ! ( "this {} bound has already been specified" , kind ) )
3239+ . help ( & format ! ( "consider removing this {} bound" , kind ) )
32203240 . emit ( )
32213241 } ) ;
32223242 }
32233243 }
32243244
3225- trait_resolutions . insert ( * ident, uniq ) ;
3245+ bounds . insert ( * ident, uniq_bounds ) ;
32263246 }
32273247 }
32283248
@@ -3232,16 +3252,19 @@ impl<'tcx> LateLintPass<'tcx> for DuplicateBounds {
32323252 bound_predicate. bounded_ty . kind
32333253 {
32343254 if let Some ( segment) = segments. first ( ) {
3235- if let Some ( trait_resolutions) = trait_resolutions. get_mut ( & segment. ident ) {
3236- for res in
3237- bound_predicate. bounds . iter ( ) . filter_map ( TraitRes :: from_bound)
3255+ if let Some ( bounds) = bounds. get_mut ( & segment. ident ) {
3256+ for res in bound_predicate. bounds . iter ( ) . filter_map ( Bound :: from_generic)
32383257 {
32393258 let span = res. span . clone ( ) ;
3240- if !trait_resolutions. insert ( res) {
3259+ let kind = res. kind . as_str ( ) ;
3260+ if !bounds. insert ( res) {
32413261 cx. struct_span_lint ( DUPLICATE_BOUNDS , span, |lint| {
3242- lint. build ( "this trait bound has already been specified" )
3243- . help ( "consider removing this trait bound" )
3244- . emit ( )
3262+ lint. build ( & format ! (
3263+ "this {} bound has already been specified" ,
3264+ kind
3265+ ) )
3266+ . help ( & format ! ( "consider removing this {} bound" , kind) )
3267+ . emit ( )
32453268 } ) ;
32463269 }
32473270 }
0 commit comments