@@ -5,10 +5,13 @@ use crate::traits::ObligationCtxt;
55
66use rustc_infer:: infer:: canonical:: Canonical ;
77use rustc_infer:: infer:: outlives:: components:: { push_outlives_components, Component } ;
8+ use rustc_infer:: infer:: resolve:: OpportunisticRegionResolver ;
89use rustc_infer:: traits:: query:: OutlivesBound ;
910use rustc_middle:: infer:: canonical:: CanonicalQueryResponse ;
1011use rustc_middle:: traits:: ObligationCause ;
11- use rustc_middle:: ty:: { self , ParamEnvAnd , Ty , TyCtxt , TypeVisitableExt } ;
12+ use rustc_middle:: ty:: { self , ParamEnvAnd , Ty , TyCtxt , TypeFolder , TypeVisitableExt } ;
13+ use rustc_span:: def_id:: CRATE_DEF_ID ;
14+ use rustc_span:: DUMMY_SP ;
1215use smallvec:: { smallvec, SmallVec } ;
1316
1417#[ derive( Copy , Clone , Debug , HashStable , TypeFoldable , TypeVisitable ) ]
@@ -52,7 +55,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
5255 ocx : & ObligationCtxt < ' _ , ' tcx > ,
5356 key : ParamEnvAnd < ' tcx , Self > ,
5457 ) -> Result < Self :: QueryResponse , NoSolution > {
55- compute_implied_outlives_bounds_inner ( ocx, key. param_env , key. value . ty )
58+ compute_implied_outlives_bounds_compat_inner ( ocx, key. param_env , key. value . ty )
5659 }
5760}
5861
@@ -63,20 +66,15 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
6366 ocx : & ObligationCtxt < ' _ , ' tcx > ,
6467 param_env : ty:: ParamEnv < ' tcx > ,
6568 ty : Ty < ' tcx > ,
66- ) -> Result < Vec < OutlivesBound < ' tcx > > , NoSolution > {
67- let normalize_op = |ty : Ty < ' tcx > | {
68- let ty = if ocx. infcx . next_trait_solver ( ) {
69- solve:: deeply_normalize ( ocx. infcx . at ( & ObligationCause :: dummy ( ) , param_env) , ty)
70- // FIXME(-Ztrait-solver=next)
71- . unwrap_or_else ( |_errs| ty)
72- } else {
73- ocx. normalize ( & ObligationCause :: dummy ( ) , param_env, ty)
74- } ;
69+ ) -> Result < & ' tcx [ OutlivesBound < ' tcx > ] , NoSolution > {
70+ let normalize_op = |ty| {
71+ let ty = ocx. normalize ( & ObligationCause :: dummy ( ) , param_env, ty) ;
7572 if !ocx. select_all_or_error ( ) . is_empty ( ) {
7673 return Err ( NoSolution ) ;
7774 }
7875 let ty = ocx. infcx . resolve_vars_if_possible ( ty) ;
79- assert ! ( !ty. has_non_region_infer( ) ) ;
76+ let ty = OpportunisticRegionResolver :: new ( & ocx. infcx ) . fold_ty ( ty) ;
77+ assert ! ( !ty. has_infer( ) ) ;
8078 Ok ( ty)
8179 } ;
8280
@@ -141,14 +139,148 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
141139 }
142140 }
143141
144- Ok ( outlives_bounds)
142+ Ok ( ocx. infcx . tcx . arena . alloc_slice ( & outlives_bounds) )
143+ }
144+
145+ pub fn compute_implied_outlives_bounds_compat_inner < ' tcx > (
146+ ocx : & ObligationCtxt < ' _ , ' tcx > ,
147+ param_env : ty:: ParamEnv < ' tcx > ,
148+ ty : Ty < ' tcx > ,
149+ ) -> Result < Vec < OutlivesBound < ' tcx > > , NoSolution > {
150+ let tcx = ocx. infcx . tcx ;
151+
152+ // Sometimes when we ask what it takes for T: WF, we get back that
153+ // U: WF is required; in that case, we push U onto this stack and
154+ // process it next. Because the resulting predicates aren't always
155+ // guaranteed to be a subset of the original type, so we need to store the
156+ // WF args we've computed in a set.
157+ let mut checked_wf_args = rustc_data_structures:: fx:: FxHashSet :: default ( ) ;
158+ let mut wf_args = vec ! [ ty. into( ) ] ;
159+
160+ let mut outlives_bounds: Vec < ty:: OutlivesPredicate < ty:: GenericArg < ' tcx > , ty:: Region < ' tcx > > > =
161+ vec ! [ ] ;
162+
163+ while let Some ( arg) = wf_args. pop ( ) {
164+ if !checked_wf_args. insert ( arg) {
165+ continue ;
166+ }
167+
168+ // Compute the obligations for `arg` to be well-formed. If `arg` is
169+ // an unresolved inference variable, just substituted an empty set
170+ // -- because the return type here is going to be things we *add*
171+ // to the environment, it's always ok for this set to be smaller
172+ // than the ultimate set. (Note: normally there won't be
173+ // unresolved inference variables here anyway, but there might be
174+ // during typeck under some circumstances.)
175+ //
176+ // FIXME(@lcnr): It's not really "always fine", having fewer implied
177+ // bounds can be backward incompatible, e.g. #101951 was caused by
178+ // us not dealing with inference vars in `TypeOutlives` predicates.
179+ let obligations = wf:: obligations ( ocx. infcx , param_env, CRATE_DEF_ID , 0 , arg, DUMMY_SP )
180+ . unwrap_or_default ( ) ;
181+
182+ for obligation in obligations {
183+ debug ! ( ?obligation) ;
184+ assert ! ( !obligation. has_escaping_bound_vars( ) ) ;
185+
186+ // While these predicates should all be implied by other parts of
187+ // the program, they are still relevant as they may constrain
188+ // inference variables, which is necessary to add the correct
189+ // implied bounds in some cases, mostly when dealing with projections.
190+ //
191+ // Another important point here: we only register `Projection`
192+ // predicates, since otherwise we might register outlives
193+ // predicates containing inference variables, and we don't
194+ // learn anything new from those.
195+ if obligation. predicate . has_non_region_infer ( ) {
196+ match obligation. predicate . kind ( ) . skip_binder ( ) {
197+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( ..) )
198+ | ty:: PredicateKind :: AliasRelate ( ..) => {
199+ ocx. register_obligation ( obligation. clone ( ) ) ;
200+ }
201+ _ => { }
202+ }
203+ }
204+
205+ let pred = match obligation. predicate . kind ( ) . no_bound_vars ( ) {
206+ None => continue ,
207+ Some ( pred) => pred,
208+ } ;
209+ match pred {
210+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( ..) )
211+ // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
212+ // if we ever support that
213+ | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: ConstArgHasType ( ..) )
214+ | ty:: PredicateKind :: Subtype ( ..)
215+ | ty:: PredicateKind :: Coerce ( ..)
216+ | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( ..) )
217+ | ty:: PredicateKind :: ObjectSafe ( ..)
218+ | ty:: PredicateKind :: Clause ( ty:: ClauseKind :: ConstEvaluatable ( ..) )
219+ | ty:: PredicateKind :: ConstEquate ( ..)
220+ | ty:: PredicateKind :: Ambiguous
221+ | ty:: PredicateKind :: AliasRelate ( ..)
222+ => { }
223+
224+ // We need to search through *all* WellFormed predicates
225+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: WellFormed ( arg) ) => {
226+ wf_args. push ( arg) ;
227+ }
228+
229+ // We need to register region relationships
230+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: RegionOutlives ( ty:: OutlivesPredicate (
231+ r_a,
232+ r_b,
233+ ) ) ) => outlives_bounds. push ( ty:: OutlivesPredicate ( r_a. into ( ) , r_b) ) ,
234+
235+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: TypeOutlives ( ty:: OutlivesPredicate (
236+ ty_a,
237+ r_b,
238+ ) ) ) => outlives_bounds. push ( ty:: OutlivesPredicate ( ty_a. into ( ) , r_b) ) ,
239+ }
240+ }
241+ }
242+
243+ // This call to `select_all_or_error` is necessary to constrain inference variables, which we
244+ // use further down when computing the implied bounds.
245+ match ocx. select_all_or_error ( ) . as_slice ( ) {
246+ [ ] => ( ) ,
247+ _ => return Err ( NoSolution ) ,
248+ }
249+
250+ // We lazily compute the outlives components as
251+ // `select_all_or_error` constrains inference variables.
252+ let mut implied_bounds = Vec :: new ( ) ;
253+ for ty:: OutlivesPredicate ( a, r_b) in outlives_bounds {
254+ match a. unpack ( ) {
255+ ty:: GenericArgKind :: Lifetime ( r_a) => {
256+ implied_bounds. push ( OutlivesBound :: RegionSubRegion ( r_b, r_a) )
257+ }
258+ ty:: GenericArgKind :: Type ( ty_a) => {
259+ let mut ty_a = ocx. infcx . resolve_vars_if_possible ( ty_a) ;
260+ // Need to manually normalize in the new solver as `wf::obligations` does not.
261+ if ocx. infcx . next_trait_solver ( ) {
262+ ty_a = solve:: deeply_normalize (
263+ ocx. infcx . at ( & ObligationCause :: dummy ( ) , param_env) ,
264+ ty_a,
265+ )
266+ . map_err ( |_errs| NoSolution ) ?;
267+ }
268+ let mut components = smallvec ! [ ] ;
269+ push_outlives_components ( tcx, ty_a, & mut components) ;
270+ implied_bounds. extend ( implied_bounds_from_components ( r_b, components) )
271+ }
272+ ty:: GenericArgKind :: Const ( _) => unreachable ! ( ) ,
273+ }
274+ }
275+
276+ Ok ( implied_bounds)
145277}
146278
147279/// When we have an implied bound that `T: 'a`, we can further break
148280/// this down to determine what relationships would have to hold for
149281/// `T: 'a` to hold. We get to assume that the caller has validated
150282/// those relationships.
151- fn implied_bounds_from_components < ' tcx > (
283+ pub fn implied_bounds_from_components < ' tcx > (
152284 sub_region : ty:: Region < ' tcx > ,
153285 sup_components : SmallVec < [ Component < ' tcx > ; 4 ] > ,
154286) -> Vec < OutlivesBound < ' tcx > > {
0 commit comments