@@ -3173,56 +3173,76 @@ declare_lint_pass!(DuplicateBounds => [DUPLICATE_BOUNDS]);
3173
3173
3174
3174
impl < ' tcx > LateLintPass < ' tcx > for DuplicateBounds {
3175
3175
fn check_generics ( & mut self , cx : & LateContext < ' tcx > , gen : & ' tcx hir:: Generics < ' _ > ) {
3176
- struct TraitRes {
3177
- res : Res ,
3176
+ struct Bound {
3177
+ kind : BoundKind ,
3178
3178
span : Span ,
3179
3179
}
3180
3180
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 ,
3187
3206
}
3188
3207
}
3189
3208
}
3190
3209
3191
- impl PartialEq for TraitRes {
3210
+ impl PartialEq for Bound {
3192
3211
fn eq ( & self , other : & Self ) -> bool {
3193
- self . res == other. res
3212
+ self . kind == other. kind
3194
3213
}
3195
3214
}
3196
3215
3197
- impl Hash for TraitRes {
3216
+ impl Hash for Bound {
3198
3217
fn hash < H : Hasher > ( & self , state : & mut H ) {
3199
- self . res . hash ( state)
3218
+ self . kind . hash ( state)
3200
3219
}
3201
3220
}
3202
3221
3203
- impl Eq for TraitRes { }
3222
+ impl Eq for Bound { }
3204
3223
3205
3224
if gen. span . from_expansion ( ) {
3206
3225
return ;
3207
3226
}
3208
3227
3209
- let mut trait_resolutions = FxHashMap :: default ( ) ;
3228
+ let mut bounds = FxHashMap :: default ( ) ;
3210
3229
for param in gen. params {
3211
3230
if let hir:: ParamName :: Plain ( ref ident) = param. name {
3212
- let mut uniq = FxHashSet :: default ( ) ;
3231
+ let mut uniq_bounds = FxHashSet :: default ( ) ;
3213
3232
3214
- for res in param. bounds . iter ( ) . filter_map ( TraitRes :: from_bound ) {
3233
+ for res in param. bounds . iter ( ) . filter_map ( Bound :: from_generic ) {
3215
3234
let span = res. span . clone ( ) ;
3216
- if !uniq. insert ( res) {
3235
+ let kind = res. kind . as_str ( ) ;
3236
+ if !uniq_bounds. insert ( res) {
3217
3237
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 ) )
3220
3240
. emit ( )
3221
3241
} ) ;
3222
3242
}
3223
3243
}
3224
3244
3225
- trait_resolutions . insert ( * ident, uniq ) ;
3245
+ bounds . insert ( * ident, uniq_bounds ) ;
3226
3246
}
3227
3247
}
3228
3248
@@ -3232,16 +3252,19 @@ impl<'tcx> LateLintPass<'tcx> for DuplicateBounds {
3232
3252
bound_predicate. bounded_ty . kind
3233
3253
{
3234
3254
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)
3238
3257
{
3239
3258
let span = res. span . clone ( ) ;
3240
- if !trait_resolutions. insert ( res) {
3259
+ let kind = res. kind . as_str ( ) ;
3260
+ if !bounds. insert ( res) {
3241
3261
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 ( )
3245
3268
} ) ;
3246
3269
}
3247
3270
}
0 commit comments