@@ -2184,30 +2184,36 @@ impl ExplicitOutlivesRequirements {
21842184 tcx : TyCtxt < ' tcx > ,
21852185 bounds : & hir:: GenericBounds < ' _ > ,
21862186 inferred_outlives : & [ ty:: Region < ' tcx > ] ,
2187+ predicate_span : Span ,
21872188 ) -> Vec < ( usize , Span ) > {
21882189 use rustc_middle:: middle:: resolve_lifetime:: Region ;
21892190
21902191 bounds
21912192 . iter ( )
21922193 . enumerate ( )
21932194 . 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 ;
22082208 }
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) )
22092216 } )
2210- . filter ( |( _, span) | !in_external_macro ( tcx. sess , * span) )
22112217 . collect ( )
22122218 }
22132219
@@ -2273,9 +2279,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
22732279 use rustc_middle:: middle:: resolve_lifetime:: Region ;
22742280
22752281 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
22792285 {
22802286 let inferred_outlives = cx. tcx . inferred_outlives_of ( def_id) ;
22812287 if inferred_outlives. is_empty ( ) {
@@ -2290,53 +2296,58 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
22902296 let mut dropped_predicate_count = 0 ;
22912297 let num_predicates = hir_generics. predicates . len ( ) ;
22922298 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+ {
23202305 (
2321- Self :: lifetimes_outliving_type ( inferred_outlives, index) ,
2306+ Self :: lifetimes_outliving_lifetime (
2307+ inferred_outlives,
2308+ region_def_id,
2309+ ) ,
23222310 & predicate. bounds ,
23232311 predicate. span ,
2324- predicate. origin == PredicateOrigin :: WhereClause ,
2312+ predicate. in_where_clause ,
23252313 )
2326- }
2327- _ => {
2314+ } else {
23282315 continue ;
23292316 }
23302317 }
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+ } ;
23342341 if relevant_lifetimes. is_empty ( ) {
23352342 continue ;
23362343 }
23372344
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+ ) ;
23402351 bound_count += bound_spans. len ( ) ;
23412352
23422353 let drop_predicate = bound_spans. len ( ) == bounds. len ( ) ;
@@ -2345,15 +2356,15 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
23452356 }
23462357
23472358 if drop_predicate && !in_where_clause {
2348- lint_spans. push ( span ) ;
2359+ lint_spans. push ( predicate_span ) ;
23492360 } else if drop_predicate && i + 1 < num_predicates {
23502361 // If all the bounds on a predicate were inferable and there are
23512362 // further predicates, we want to eat the trailing comma.
23522363 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 ( ) ) ) ;
23542365 } else {
23552366 where_lint_spans. extend ( self . consolidate_outlives_bound_spans (
2356- span . shrink_to_lo ( ) ,
2367+ predicate_span . shrink_to_lo ( ) ,
23572368 bounds,
23582369 bound_spans,
23592370 ) ) ;
@@ -2374,24 +2385,35 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
23742385 } else {
23752386 hir_generics. span . shrink_to_hi ( ) . to ( where_span)
23762387 } ;
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+ }
23782395 } else {
23792396 lint_spans. extend ( where_lint_spans) ;
23802397 }
23812398
23822399 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+
23832408 cx. struct_span_lint (
23842409 EXPLICIT_OUTLIVES_REQUIREMENTS ,
23852410 lint_spans. clone ( ) ,
23862411 fluent:: lint_builtin_explicit_outlives,
23872412 |lint| {
23882413 lint. set_arg ( "count" , bound_count) . multipart_suggestion (
23892414 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,
23952417 )
23962418 } ,
23972419 ) ;
0 commit comments