@@ -2184,30 +2184,36 @@ impl ExplicitOutlivesRequirements {
2184
2184
tcx : TyCtxt < ' tcx > ,
2185
2185
bounds : & hir:: GenericBounds < ' _ > ,
2186
2186
inferred_outlives : & [ ty:: Region < ' tcx > ] ,
2187
+ predicate_span : Span ,
2187
2188
) -> Vec < ( usize , Span ) > {
2188
2189
use rustc_middle:: middle:: resolve_lifetime:: Region ;
2189
2190
2190
2191
bounds
2191
2192
. iter ( )
2192
2193
. enumerate ( )
2193
2194
. filter_map ( |( i, bound) | {
2194
- if let hir:: GenericBound :: Outlives ( lifetime) = bound {
2195
- let is_inferred = match tcx. named_region ( lifetime. hir_id ) {
2196
- Some ( Region :: EarlyBound ( def_id) ) => inferred_outlives. iter ( ) . any ( |r| {
2197
- if let ty:: ReEarlyBound ( ebr) = * * r {
2198
- ebr. def_id == def_id
2199
- } else {
2200
- false
2201
- }
2202
- } ) ,
2203
- _ => false ,
2204
- } ;
2205
- is_inferred. then_some ( ( i, bound. span ( ) ) )
2206
- } else {
2207
- None
2195
+ let hir:: GenericBound :: Outlives ( lifetime) = bound else {
2196
+ return None ;
2197
+ } ;
2198
+
2199
+ let is_inferred = match tcx. named_region ( lifetime. hir_id ) {
2200
+ Some ( Region :: EarlyBound ( def_id) ) => inferred_outlives
2201
+ . iter ( )
2202
+ . any ( |r| matches ! ( * * r, ty:: ReEarlyBound ( ebr) if { ebr. def_id == def_id } ) ) ,
2203
+ _ => false ,
2204
+ } ;
2205
+
2206
+ if !is_inferred {
2207
+ return None ;
2208
2208
}
2209
+
2210
+ let span = bound. span ( ) . find_ancestor_inside ( predicate_span) ?;
2211
+ if in_external_macro ( tcx. sess , span) {
2212
+ return None ;
2213
+ }
2214
+
2215
+ Some ( ( i, span) )
2209
2216
} )
2210
- . filter ( |( _, span) | !in_external_macro ( tcx. sess , * span) )
2211
2217
. collect ( )
2212
2218
}
2213
2219
@@ -2273,9 +2279,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
2273
2279
use rustc_middle:: middle:: resolve_lifetime:: Region ;
2274
2280
2275
2281
let def_id = item. owner_id . def_id ;
2276
- if let hir:: ItemKind :: Struct ( _, ref hir_generics)
2277
- | hir:: ItemKind :: Enum ( _, ref hir_generics)
2278
- | hir:: ItemKind :: Union ( _, ref hir_generics) = item. kind
2282
+ if let hir:: ItemKind :: Struct ( _, hir_generics)
2283
+ | hir:: ItemKind :: Enum ( _, hir_generics)
2284
+ | hir:: ItemKind :: Union ( _, hir_generics) = item. kind
2279
2285
{
2280
2286
let inferred_outlives = cx. tcx . inferred_outlives_of ( def_id) ;
2281
2287
if inferred_outlives. is_empty ( ) {
@@ -2290,53 +2296,58 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
2290
2296
let mut dropped_predicate_count = 0 ;
2291
2297
let num_predicates = hir_generics. predicates . len ( ) ;
2292
2298
for ( i, where_predicate) in hir_generics. predicates . iter ( ) . enumerate ( ) {
2293
- let ( relevant_lifetimes, bounds, span, in_where_clause) = match where_predicate {
2294
- hir:: WherePredicate :: RegionPredicate ( predicate) => {
2295
- if let Some ( Region :: EarlyBound ( region_def_id) ) =
2296
- cx. tcx . named_region ( predicate. lifetime . hir_id )
2297
- {
2298
- (
2299
- Self :: lifetimes_outliving_lifetime (
2300
- inferred_outlives,
2301
- region_def_id,
2302
- ) ,
2303
- & predicate. bounds ,
2304
- predicate. span ,
2305
- predicate. in_where_clause ,
2306
- )
2307
- } else {
2308
- continue ;
2309
- }
2310
- }
2311
- hir:: WherePredicate :: BoundPredicate ( predicate) => {
2312
- // FIXME we can also infer bounds on associated types,
2313
- // and should check for them here.
2314
- match predicate. bounded_ty . kind {
2315
- hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , ref path) ) => {
2316
- let Res :: Def ( DefKind :: TyParam , def_id) = path. res else {
2317
- continue
2318
- } ;
2319
- let index = ty_generics. param_def_id_to_index [ & def_id] ;
2299
+ let ( relevant_lifetimes, bounds, predicate_span, in_where_clause) =
2300
+ match where_predicate {
2301
+ hir:: WherePredicate :: RegionPredicate ( predicate) => {
2302
+ if let Some ( Region :: EarlyBound ( region_def_id) ) =
2303
+ cx. tcx . named_region ( predicate. lifetime . hir_id )
2304
+ {
2320
2305
(
2321
- Self :: lifetimes_outliving_type ( inferred_outlives, index) ,
2306
+ Self :: lifetimes_outliving_lifetime (
2307
+ inferred_outlives,
2308
+ region_def_id,
2309
+ ) ,
2322
2310
& predicate. bounds ,
2323
2311
predicate. span ,
2324
- predicate. origin == PredicateOrigin :: WhereClause ,
2312
+ predicate. in_where_clause ,
2325
2313
)
2326
- }
2327
- _ => {
2314
+ } else {
2328
2315
continue ;
2329
2316
}
2330
2317
}
2331
- }
2332
- _ => continue ,
2333
- } ;
2318
+ hir:: WherePredicate :: BoundPredicate ( predicate) => {
2319
+ // FIXME we can also infer bounds on associated types,
2320
+ // and should check for them here.
2321
+ match predicate. bounded_ty . kind {
2322
+ hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , path) ) => {
2323
+ let Res :: Def ( DefKind :: TyParam , def_id) = path. res else {
2324
+ continue ;
2325
+ } ;
2326
+ let index = ty_generics. param_def_id_to_index [ & def_id] ;
2327
+ (
2328
+ Self :: lifetimes_outliving_type ( inferred_outlives, index) ,
2329
+ & predicate. bounds ,
2330
+ predicate. span ,
2331
+ predicate. origin == PredicateOrigin :: WhereClause ,
2332
+ )
2333
+ }
2334
+ _ => {
2335
+ continue ;
2336
+ }
2337
+ }
2338
+ }
2339
+ _ => continue ,
2340
+ } ;
2334
2341
if relevant_lifetimes. is_empty ( ) {
2335
2342
continue ;
2336
2343
}
2337
2344
2338
- let bound_spans =
2339
- self . collect_outlives_bound_spans ( cx. tcx , bounds, & relevant_lifetimes) ;
2345
+ let bound_spans = self . collect_outlives_bound_spans (
2346
+ cx. tcx ,
2347
+ bounds,
2348
+ & relevant_lifetimes,
2349
+ predicate_span,
2350
+ ) ;
2340
2351
bound_count += bound_spans. len ( ) ;
2341
2352
2342
2353
let drop_predicate = bound_spans. len ( ) == bounds. len ( ) ;
@@ -2345,15 +2356,15 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
2345
2356
}
2346
2357
2347
2358
if drop_predicate && !in_where_clause {
2348
- lint_spans. push ( span ) ;
2359
+ lint_spans. push ( predicate_span ) ;
2349
2360
} else if drop_predicate && i + 1 < num_predicates {
2350
2361
// If all the bounds on a predicate were inferable and there are
2351
2362
// further predicates, we want to eat the trailing comma.
2352
2363
let next_predicate_span = hir_generics. predicates [ i + 1 ] . span ( ) ;
2353
- where_lint_spans. push ( span . to ( next_predicate_span. shrink_to_lo ( ) ) ) ;
2364
+ where_lint_spans. push ( predicate_span . to ( next_predicate_span. shrink_to_lo ( ) ) ) ;
2354
2365
} else {
2355
2366
where_lint_spans. extend ( self . consolidate_outlives_bound_spans (
2356
- span . shrink_to_lo ( ) ,
2367
+ predicate_span . shrink_to_lo ( ) ,
2357
2368
bounds,
2358
2369
bound_spans,
2359
2370
) ) ;
@@ -2374,24 +2385,35 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
2374
2385
} else {
2375
2386
hir_generics. span . shrink_to_hi ( ) . to ( where_span)
2376
2387
} ;
2377
- lint_spans. push ( full_where_span) ;
2388
+
2389
+ // Due to macro expansions, the `full_where_span` might not actually contain all predicates.
2390
+ if where_lint_spans. iter ( ) . all ( |& sp| full_where_span. contains ( sp) ) {
2391
+ lint_spans. push ( full_where_span) ;
2392
+ } else {
2393
+ lint_spans. extend ( where_lint_spans) ;
2394
+ }
2378
2395
} else {
2379
2396
lint_spans. extend ( where_lint_spans) ;
2380
2397
}
2381
2398
2382
2399
if !lint_spans. is_empty ( ) {
2400
+ // Do not automatically delete outlives requirements from macros.
2401
+ let applicability = if lint_spans. iter ( ) . all ( |sp| sp. can_be_used_for_suggestions ( ) )
2402
+ {
2403
+ Applicability :: MachineApplicable
2404
+ } else {
2405
+ Applicability :: MaybeIncorrect
2406
+ } ;
2407
+
2383
2408
cx. struct_span_lint (
2384
2409
EXPLICIT_OUTLIVES_REQUIREMENTS ,
2385
2410
lint_spans. clone ( ) ,
2386
2411
fluent:: lint_builtin_explicit_outlives,
2387
2412
|lint| {
2388
2413
lint. set_arg ( "count" , bound_count) . multipart_suggestion (
2389
2414
fluent:: suggestion,
2390
- lint_spans
2391
- . into_iter ( )
2392
- . map ( |span| ( span, String :: new ( ) ) )
2393
- . collect :: < Vec < _ > > ( ) ,
2394
- Applicability :: MachineApplicable ,
2415
+ lint_spans. into_iter ( ) . map ( |span| ( span, String :: new ( ) ) ) . collect ( ) ,
2416
+ applicability,
2395
2417
)
2396
2418
} ,
2397
2419
) ;
0 commit comments