Change:
This code compiles after although it shouldn't: () This is similar to in that we're not taking into account placeholder regions when "promoting" type-tests from the closure to its caller: label T-types regression-from-stable-to-beta C-bug A-NLL I-unsound <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
I guess it would be an easy fix claim
The unsoundness exploitation in can easily be adapted for this issue, so it is in fact a soundness issue:
issue touched in today's T-compiler meeting, . Will also be discussed tomorrow during the T-types meeting.
WG-prioritization assigning priority (). label -I-prioritize +P-critical

Discussion:
/// The idea then is to lower the `T: 'X` constraint into multiple /// bounds -- e.g., if `'X` is the union of two free lifetimes, /// `'1` and `'2`, then we would create `T: '1` and `T: '2`. <ins> #[instrument(level = "debug", skip(self, infcx, propagated_outlives_requirements))] </ins> fn try_promote_type_test( &self, infcx: &InferCtxt<'_, 'tcx>,

return false; }; <ins> debug!("subject = {:?}", subject); let r_scc = self.constraint_sccs.scc(*lower_bound); debug!( "lower_bound = {:?} r_scc={:?} universe={:?}", lower_bound, r_scc, self.scc_universes[r_scc] ); // If the type test requires that `T: 'a` where `'a` is a // placeholder from another universe, that effectively requires // `T: 'static`, so we have to propagate that requirement. // // It doesn't matter *what* universe because the promoted `T` will // always be in the root universe. if let Some(p) = self.scc_values.placeholders_contained_in(r_scc).next() { debug!("encountered placeholder in higher universe: {:?}, requiring 'static", p); let static_r = self.universal_regions.fr_static; propagated_outlives_requirements.push(ClosureOutlivesRequirement { subject, outlived_free_region: static_r, blame_span: locations.span(body), category: ConstraintCategory::Boring, }); // we can return here -- the code below might push add'l constraints // but they would all be weaker than this one. return true; } </ins> // For each region outlived by lower_bound find a non-local, // universal region (it may be the same region) and add it to // `ClosureOutlivesRequirement`. <del> let r_scc = self.constraint_sccs.scc(*lower_bound); </del> for ur in self.scc_values.universal_regions_outlived_by(r_scc) { <ins> debug!("universal_region_outlived_by ur={:?}", ur); </ins> // Check whether we can already prove that the "subject" outlives `ur`. // If so, we don't have to propagate this requirement to our caller. //

continue; } <del> debug!("try_promote_type_test: ur={:?}", ur); </del> let non_local_ub = self.universal_region_relations.non_local_upper_bounds(ur); debug!("try_promote_type_test: non_local_ub={:?}", non_local_ub);

/// will use it's *external name*, which will be a `RegionKind` /// variant that can be used in query responses such as /// `ReEarlyBound`. <ins> #[instrument(level = "debug", skip(self, infcx))] </ins> fn try_promote_type_test_subject( &self, infcx: &InferCtxt<'_, 'tcx>,

) -> Option<ClosureOutlivesSubject<'tcx>> { let tcx = infcx.tcx; <del> debug!("try_promote_type_test_subject(ty = {:?})", ty); </del> let ty = tcx.fold_regions(ty, |r, _depth| { let region_vid = self.to_region_vid(r);

//~| ERROR `T` does not live long enough //~| ERROR `T` does not live long enough //~| ERROR `T` does not live long enough <ins> //~| ERROR `T` may not live long enough </ins> // // FIXME: This error is bogus, but it arises because we try to validate // that `<() as Foo<T>>::Type<'a>` is valid, which requires proving

LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); |                                                          ^^^^^^^^^ <ins> error[E0310]: the parameter type `T` may not live long enough --> $DIR/issue-91139.rs:16:58 | LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); |                                                          ^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | LL | fn foo<T: 'static>() { |         +++++++++ </ins> error: `T` does not live long enough --> $DIR/issue-91139.rs:16:58 |

LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| (); |                                                          ^^^^^^^^^ <del> error: aborting due to 8 previous errors </del> <ins> error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0310`. </ins>

<ins> // Regression test for #98693. // // The closure encounters an obligation that `T` must outlive `!U1`, // a placeholder from universe U1. We were ignoring this placeholder // when promoting the constraint to the enclosing function, and // thus incorrectly judging the closure to be safe. fn assert_static<T>() where for<'a> T: 'a, { } fn test<T>() { || { //~^ ERROR the parameter type `T` may not live long enough assert_static::<T>(); }; } fn main() {} </ins>

<ins> error[E0310]: the parameter type `T` may not live long enough --> $DIR/issue-98693.rs:15:5 | LL | /     || { LL | | LL | |         assert_static::<T>(); LL | |     }; | |_____^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | LL | fn test<T: 'static>() { |          +++++++++ error: aborting due to previous error For more information about this error, try `rustc --explain E0310`. </ins>