@@ -5,10 +5,13 @@ use crate::traits::ObligationCtxt;
5
5
6
6
use rustc_infer:: infer:: canonical:: Canonical ;
7
7
use rustc_infer:: infer:: outlives:: components:: { push_outlives_components, Component } ;
8
+ use rustc_infer:: infer:: resolve:: OpportunisticRegionResolver ;
8
9
use rustc_infer:: traits:: query:: OutlivesBound ;
9
10
use rustc_middle:: infer:: canonical:: CanonicalQueryResponse ;
10
11
use 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 ;
12
15
use smallvec:: { smallvec, SmallVec } ;
13
16
14
17
#[ derive( Copy , Clone , Debug , HashStable , TypeFoldable , TypeVisitable ) ]
@@ -52,7 +55,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
52
55
ocx : & ObligationCtxt < ' _ , ' tcx > ,
53
56
key : ParamEnvAnd < ' tcx , Self > ,
54
57
) -> 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 )
56
59
}
57
60
}
58
61
@@ -63,20 +66,15 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
63
66
ocx : & ObligationCtxt < ' _ , ' tcx > ,
64
67
param_env : ty:: ParamEnv < ' tcx > ,
65
68
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) ;
75
72
if !ocx. select_all_or_error ( ) . is_empty ( ) {
76
73
return Err ( NoSolution ) ;
77
74
}
78
75
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( ) ) ;
80
78
Ok ( ty)
81
79
} ;
82
80
@@ -141,14 +139,148 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
141
139
}
142
140
}
143
141
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)
145
277
}
146
278
147
279
/// When we have an implied bound that `T: 'a`, we can further break
148
280
/// this down to determine what relationships would have to hold for
149
281
/// `T: 'a` to hold. We get to assume that the caller has validated
150
282
/// those relationships.
151
- fn implied_bounds_from_components < ' tcx > (
283
+ pub fn implied_bounds_from_components < ' tcx > (
152
284
sub_region : ty:: Region < ' tcx > ,
153
285
sup_components : SmallVec < [ Component < ' tcx > ; 4 ] > ,
154
286
) -> Vec < OutlivesBound < ' tcx > > {
0 commit comments