@@ -9,8 +9,6 @@ use rustc_infer::traits::query::OutlivesBound;
99use rustc_middle:: infer:: canonical:: CanonicalQueryResponse ;
1010use rustc_middle:: traits:: ObligationCause ;
1111use rustc_middle:: ty:: { self , ParamEnvAnd , Ty , TyCtxt , TypeVisitableExt } ;
12- use rustc_span:: def_id:: CRATE_DEF_ID ;
13- use rustc_span:: DUMMY_SP ;
1412use smallvec:: { smallvec, SmallVec } ;
1513
1614#[ derive( Copy , Clone , Debug , HashStable , TypeFoldable , TypeVisitable ) ]
@@ -58,69 +56,52 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
5856 }
5957}
6058
59+ /// For the sake of completeness, we should be careful when dealing with inference artifacts:
60+ /// - `ty` must be fully resolved.
61+ /// - `normalize_op` must return a fully resolved type.
6162pub fn compute_implied_outlives_bounds_inner < ' tcx > (
6263 ocx : & ObligationCtxt < ' _ , ' tcx > ,
6364 param_env : ty:: ParamEnv < ' tcx > ,
6465 ty : Ty < ' tcx > ,
6566) -> Result < Vec < OutlivesBound < ' tcx > > , NoSolution > {
66- let tcx = ocx. infcx . tcx ;
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+ } ;
75+ if !ocx. select_all_or_error ( ) . is_empty ( ) {
76+ return Err ( NoSolution ) ;
77+ }
78+ let ty = ocx. infcx . resolve_vars_if_possible ( ty) ;
79+ assert ! ( !ty. has_non_region_infer( ) ) ;
80+ Ok ( ty)
81+ } ;
6782
6883 // Sometimes when we ask what it takes for T: WF, we get back that
6984 // U: WF is required; in that case, we push U onto this stack and
7085 // process it next. Because the resulting predicates aren't always
7186 // guaranteed to be a subset of the original type, so we need to store the
7287 // WF args we've computed in a set.
7388 let mut checked_wf_args = rustc_data_structures:: fx:: FxHashSet :: default ( ) ;
74- let mut wf_args = vec ! [ ty. into( ) ] ;
89+ let mut wf_args = vec ! [ ty. into( ) , normalize_op ( ty ) ? . into ( ) ] ;
7590
76- let mut outlives_bounds: Vec < ty:: OutlivesPredicate < ty:: GenericArg < ' tcx > , ty:: Region < ' tcx > > > =
77- vec ! [ ] ;
91+ let mut outlives_bounds: Vec < OutlivesBound < ' tcx > > = vec ! [ ] ;
7892
7993 while let Some ( arg) = wf_args. pop ( ) {
8094 if !checked_wf_args. insert ( arg) {
8195 continue ;
8296 }
8397
84- // Compute the obligations for `arg` to be well-formed. If `arg` is
85- // an unresolved inference variable, just substituted an empty set
86- // -- because the return type here is going to be things we *add*
87- // to the environment, it's always ok for this set to be smaller
88- // than the ultimate set. (Note: normally there won't be
89- // unresolved inference variables here anyway, but there might be
90- // during typeck under some circumstances.)
91- //
92- // FIXME(@lcnr): It's not really "always fine", having fewer implied
93- // bounds can be backward incompatible, e.g. #101951 was caused by
94- // us not dealing with inference vars in `TypeOutlives` predicates.
95- let obligations = wf:: obligations ( ocx. infcx , param_env, CRATE_DEF_ID , 0 , arg, DUMMY_SP )
96- . unwrap_or_default ( ) ;
97-
98- for obligation in obligations {
99- debug ! ( ?obligation) ;
98+ // From the full set of obligations, just filter down to the region relationships.
99+ for obligation in
100+ wf:: unnormalized_obligations ( ocx. infcx , param_env, arg) . into_iter ( ) . flatten ( )
101+ {
100102 assert ! ( !obligation. has_escaping_bound_vars( ) ) ;
101-
102- // While these predicates should all be implied by other parts of
103- // the program, they are still relevant as they may constrain
104- // inference variables, which is necessary to add the correct
105- // implied bounds in some cases, mostly when dealing with projections.
106- //
107- // Another important point here: we only register `Projection`
108- // predicates, since otherwise we might register outlives
109- // predicates containing inference variables, and we don't
110- // learn anything new from those.
111- if obligation. predicate . has_non_region_infer ( ) {
112- match obligation. predicate . kind ( ) . skip_binder ( ) {
113- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( ..) )
114- | ty:: PredicateKind :: AliasRelate ( ..) => {
115- ocx. register_obligation ( obligation. clone ( ) ) ;
116- }
117- _ => { }
118- }
119- }
120-
121- let pred = match obligation. predicate . kind ( ) . no_bound_vars ( ) {
122- None => continue ,
123- Some ( pred) => pred,
103+ let Some ( pred) = obligation. predicate . kind ( ) . no_bound_vars ( ) else {
104+ continue ;
124105 } ;
125106 match pred {
126107 ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( ..) )
@@ -143,53 +124,24 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
143124 }
144125
145126 // We need to register region relationships
146- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: RegionOutlives ( ty:: OutlivesPredicate (
147- r_a,
148- r_b,
149- ) ) ) => outlives_bounds. push ( ty:: OutlivesPredicate ( r_a. into ( ) , r_b) ) ,
127+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: RegionOutlives (
128+ ty:: OutlivesPredicate ( r_a, r_b) ,
129+ ) ) => outlives_bounds. push ( OutlivesBound :: RegionSubRegion ( r_b, r_a) ) ,
150130
151131 ty:: PredicateKind :: Clause ( ty:: ClauseKind :: TypeOutlives ( ty:: OutlivesPredicate (
152132 ty_a,
153133 r_b,
154- ) ) ) => outlives_bounds. push ( ty:: OutlivesPredicate ( ty_a. into ( ) , r_b) ) ,
155- }
156- }
157- }
158-
159- // This call to `select_all_or_error` is necessary to constrain inference variables, which we
160- // use further down when computing the implied bounds.
161- match ocx. select_all_or_error ( ) . as_slice ( ) {
162- [ ] => ( ) ,
163- _ => return Err ( NoSolution ) ,
164- }
165-
166- // We lazily compute the outlives components as
167- // `select_all_or_error` constrains inference variables.
168- let mut implied_bounds = Vec :: new ( ) ;
169- for ty:: OutlivesPredicate ( a, r_b) in outlives_bounds {
170- match a. unpack ( ) {
171- ty:: GenericArgKind :: Lifetime ( r_a) => {
172- implied_bounds. push ( OutlivesBound :: RegionSubRegion ( r_b, r_a) )
173- }
174- ty:: GenericArgKind :: Type ( ty_a) => {
175- let mut ty_a = ocx. infcx . resolve_vars_if_possible ( ty_a) ;
176- // Need to manually normalize in the new solver as `wf::obligations` does not.
177- if ocx. infcx . next_trait_solver ( ) {
178- ty_a = solve:: deeply_normalize (
179- ocx. infcx . at ( & ObligationCause :: dummy ( ) , param_env) ,
180- ty_a,
181- )
182- . map_err ( |_errs| NoSolution ) ?;
134+ ) ) ) => {
135+ let ty_a = normalize_op ( ty_a) ?;
136+ let mut components = smallvec ! [ ] ;
137+ push_outlives_components ( ocx. infcx . tcx , ty_a, & mut components) ;
138+ outlives_bounds. extend ( implied_bounds_from_components ( r_b, components) )
183139 }
184- let mut components = smallvec ! [ ] ;
185- push_outlives_components ( tcx, ty_a, & mut components) ;
186- implied_bounds. extend ( implied_bounds_from_components ( r_b, components) )
187140 }
188- ty:: GenericArgKind :: Const ( _) => unreachable ! ( ) ,
189141 }
190142 }
191143
192- Ok ( implied_bounds )
144+ Ok ( outlives_bounds )
193145}
194146
195147/// When we have an implied bound that `T: 'a`, we can further break
0 commit comments