]>
Commit | Line | Data |
---|---|---|
abe05a73 | 1 | //! Code that handles "type-outlives" constraints like `T: 'a`. This |
a1dfa0c6 | 2 | //! is based on the `push_outlives_components` function defined on the tcx, |
abe05a73 XL |
3 | //! but it adds a bit of heuristics on top, in particular to deal with |
4 | //! associated types and projections. | |
5 | //! | |
6 | //! When we process a given `T: 'a` obligation, we may produce two | |
7 | //! kinds of constraints for the region inferencer: | |
8 | //! | |
9 | //! - Relationships between inference variables and other regions. | |
10 | //! For example, if we have `&'?0 u32: 'a`, then we would produce | |
11 | //! a constraint that `'a <= '?0`. | |
12 | //! - "Verifys" that must be checked after inferencing is done. | |
13 | //! For example, if we know that, for some type parameter `T`, | |
14 | //! `T: 'a + 'b`, and we have a requirement that `T: '?1`, | |
15 | //! then we add a "verify" that checks that `'?1 <= 'a || '?1 <= 'b`. | |
16 | //! - Note the difference with the previous case: here, the region | |
17 | //! variable must be less than something else, so this doesn't | |
18 | //! affect how inference works (it finds the smallest region that | |
19 | //! will do); it's just a post-condition that we have to check. | |
20 | //! | |
21 | //! **The key point is that once this function is done, we have | |
22 | //! reduced all of our "type-region outlives" obligations into relationships | |
23 | //! between individual regions.** | |
24 | //! | |
25 | //! One key input to this function is the set of "region-bound pairs". | |
26 | //! These are basically the relationships between type parameters and | |
27 | //! regions that are in scope at the point where the outlives | |
28 | //! obligation was incurred. **When type-checking a function, | |
29 | //! particularly in the face of closures, this is not known until | |
30 | //! regionck runs!** This is because some of those bounds come | |
31 | //! from things we have yet to infer. | |
32 | //! | |
33 | //! Consider: | |
34 | //! | |
35 | //! ``` | |
36 | //! fn bar<T>(a: T, b: impl for<'a> Fn(&'a T)); | |
37 | //! fn foo<T>(x: T) { | |
38 | //! bar(x, |y| { ... }) | |
39 | //! // ^ closure arg | |
40 | //! } | |
41 | //! ``` | |
42 | //! | |
43 | //! Here, the type of `y` may involve inference variables and the | |
44 | //! like, and it may also contain implied bounds that are needed to | |
45 | //! type-check the closure body (e.g., here it informs us that `T` | |
46 | //! outlives the late-bound region `'a`). | |
47 | //! | |
48 | //! Note that by delaying the gathering of implied bounds until all | |
49 | //! inference information is known, we may find relationships between | |
50 | //! bound regions and other regions in the environment. For example, | |
51 | //! when we first check a closure like the one expected as argument | |
52 | //! to `foo`: | |
53 | //! | |
54 | //! ``` | |
55 | //! fn foo<U, F: for<'a> FnMut(&'a U)>(_f: F) {} | |
56 | //! ``` | |
57 | //! | |
9fa01778 | 58 | //! the type of the closure's first argument would be `&'a ?U`. We |
abe05a73 XL |
59 | //! might later infer `?U` to something like `&'b u32`, which would |
60 | //! imply that `'b: 'a`. | |
61 | ||
9fa01778 XL |
62 | use crate::infer::outlives::env::RegionBoundPairs; |
63 | use crate::infer::outlives::verify::VerifyBoundCx; | |
f9f354fc XL |
64 | use crate::infer::{ |
65 | self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound, | |
66 | }; | |
9fa01778 | 67 | use crate::traits::ObligationCause; |
ba9703b0 XL |
68 | use rustc_middle::ty::outlives::Component; |
69 | use rustc_middle::ty::subst::GenericArgKind; | |
70 | use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable}; | |
74b04a01 | 71 | |
dfeec247 | 72 | use rustc_data_structures::fx::FxHashMap; |
f9f354fc | 73 | use rustc_data_structures::undo_log::UndoLogs; |
dfeec247 | 74 | use rustc_hir as hir; |
74b04a01 | 75 | use smallvec::smallvec; |
abe05a73 | 76 | |
dc9dc135 | 77 | impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { |
abe05a73 XL |
78 | /// Registers that the given region obligation must be resolved |
79 | /// from within the scope of `body_id`. These regions are enqueued | |
80 | /// and later processed by regionck, when full type information is | |
81 | /// available (see `region_obligations` field for more | |
82 | /// information). | |
83 | pub fn register_region_obligation( | |
84 | &self, | |
9fa01778 | 85 | body_id: hir::HirId, |
abe05a73 XL |
86 | obligation: RegionObligation<'tcx>, |
87 | ) { | |
dfeec247 | 88 | debug!("register_region_obligation(body_id={:?}, obligation={:?})", body_id, obligation); |
ff7c6d11 | 89 | |
f9f354fc XL |
90 | let mut inner = self.inner.borrow_mut(); |
91 | inner.undo_log.push(UndoLog::PushRegionObligation); | |
92 | inner.region_obligations.push((body_id, obligation)); | |
abe05a73 XL |
93 | } |
94 | ||
0bf4aa26 XL |
95 | pub fn register_region_obligation_with_cause( |
96 | &self, | |
97 | sup_type: Ty<'tcx>, | |
98 | sub_region: Region<'tcx>, | |
99 | cause: &ObligationCause<'tcx>, | |
100 | ) { | |
101 | let origin = SubregionOrigin::from_obligation_cause(cause, || { | |
102 | infer::RelateParamBound(cause.span, sup_type) | |
103 | }); | |
104 | ||
105 | self.register_region_obligation( | |
106 | cause.body_id, | |
dfeec247 | 107 | RegionObligation { sup_type, sub_region, origin }, |
0bf4aa26 XL |
108 | ); |
109 | } | |
110 | ||
0531ce1d | 111 | /// Trait queries just want to pass back type obligations "as is" |
9fa01778 | 112 | pub fn take_registered_region_obligations(&self) -> Vec<(hir::HirId, RegionObligation<'tcx>)> { |
74b04a01 | 113 | ::std::mem::take(&mut self.inner.borrow_mut().region_obligations) |
0531ce1d XL |
114 | } |
115 | ||
abe05a73 XL |
116 | /// Process the region obligations that must be proven (during |
117 | /// `regionck`) for the given `body_id`, given information about | |
118 | /// the region bounds in scope and so forth. This function must be | |
119 | /// invoked for all relevant body-ids before region inference is | |
120 | /// done (or else an assert will fire). | |
121 | /// | |
122 | /// See the `region_obligations` field of `InferCtxt` for some | |
0531ce1d | 123 | /// comments about how this function fits into the overall expected |
a1dfa0c6 | 124 | /// flow of the inferencer. The key point is that it is |
abe05a73 XL |
125 | /// invoked after all type-inference variables have been bound -- |
126 | /// towards the end of regionck. This also ensures that the | |
127 | /// region-bound-pairs are available (see comments above regarding | |
128 | /// closures). | |
129 | /// | |
130 | /// # Parameters | |
131 | /// | |
132 | /// - `region_bound_pairs`: the set of region bounds implied by | |
133 | /// the parameters and where-clauses. In particular, each pair | |
134 | /// `('a, K)` in this list tells us that the bounds in scope | |
135 | /// indicate that `K: 'a`, where `K` is either a generic | |
136 | /// parameter like `T` or a projection like `T::Item`. | |
137 | /// - `implicit_region_bound`: if some, this is a region bound | |
138 | /// that is considered to hold for all type parameters (the | |
139 | /// function body). | |
140 | /// - `param_env` is the parameter environment for the enclosing function. | |
141 | /// - `body_id` is the body-id whose region obligations are being | |
142 | /// processed. | |
143 | /// | |
144 | /// # Returns | |
145 | /// | |
146 | /// This function may have to perform normalizations, and hence it | |
147 | /// returns an `InferOk` with subobligations that must be | |
148 | /// processed. | |
149 | pub fn process_registered_region_obligations( | |
150 | &self, | |
9fa01778 | 151 | region_bound_pairs_map: &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>, |
abe05a73 XL |
152 | implicit_region_bound: Option<ty::Region<'tcx>>, |
153 | param_env: ty::ParamEnv<'tcx>, | |
abe05a73 XL |
154 | ) { |
155 | assert!( | |
156 | !self.in_snapshot.get(), | |
157 | "cannot process registered region obligations in a snapshot" | |
158 | ); | |
159 | ||
ff7c6d11 XL |
160 | debug!("process_registered_region_obligations()"); |
161 | ||
0bf4aa26 | 162 | let my_region_obligations = self.take_registered_region_obligations(); |
abe05a73 | 163 | |
dfeec247 | 164 | for (body_id, RegionObligation { sup_type, sub_region, origin }) in my_region_obligations { |
ff7c6d11 | 165 | debug!( |
0bf4aa26 XL |
166 | "process_registered_region_obligations: sup_type={:?} sub_region={:?} origin={:?}", |
167 | sup_type, sub_region, origin | |
ff7c6d11 XL |
168 | ); |
169 | ||
dc9dc135 | 170 | let sup_type = self.resolve_vars_if_possible(&sup_type); |
0bf4aa26 XL |
171 | |
172 | if let Some(region_bound_pairs) = region_bound_pairs_map.get(&body_id) { | |
173 | let outlives = &mut TypeOutlives::new( | |
174 | self, | |
175 | self.tcx, | |
176 | ®ion_bound_pairs, | |
177 | implicit_region_bound, | |
178 | param_env, | |
179 | ); | |
180 | outlives.type_must_outlive(origin, sup_type, sub_region); | |
181 | } else { | |
182 | self.tcx.sess.delay_span_bug( | |
183 | origin.span(), | |
184 | &format!("no region-bound-pairs for {:?}", body_id), | |
185 | ) | |
186 | } | |
abe05a73 XL |
187 | } |
188 | } | |
189 | ||
190 | /// Processes a single ad-hoc region obligation that was not | |
191 | /// registered in advance. | |
192 | pub fn type_must_outlive( | |
193 | &self, | |
0bf4aa26 | 194 | region_bound_pairs: &RegionBoundPairs<'tcx>, |
abe05a73 XL |
195 | implicit_region_bound: Option<ty::Region<'tcx>>, |
196 | param_env: ty::ParamEnv<'tcx>, | |
197 | origin: infer::SubregionOrigin<'tcx>, | |
198 | ty: Ty<'tcx>, | |
199 | region: ty::Region<'tcx>, | |
200 | ) { | |
8faf50e0 XL |
201 | let outlives = &mut TypeOutlives::new( |
202 | self, | |
203 | self.tcx, | |
204 | region_bound_pairs, | |
205 | implicit_region_bound, | |
206 | param_env, | |
207 | ); | |
dc9dc135 | 208 | let ty = self.resolve_vars_if_possible(&ty); |
abe05a73 XL |
209 | outlives.type_must_outlive(origin, ty, region); |
210 | } | |
abe05a73 XL |
211 | } |
212 | ||
8faf50e0 | 213 | /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a` |
60c5eb7d | 214 | /// obligation into a series of `'a: 'b` constraints and "verify"s, as |
8faf50e0 XL |
215 | /// described on the module comment. The final constraints are emitted |
216 | /// via a "delegate" of type `D` -- this is usually the `infcx`, which | |
217 | /// accrues them into the `region_obligations` code, but for NLL we | |
218 | /// use something else. | |
dc9dc135 | 219 | pub struct TypeOutlives<'cx, 'tcx, D> |
8faf50e0 XL |
220 | where |
221 | D: TypeOutlivesDelegate<'tcx>, | |
222 | { | |
abe05a73 XL |
223 | // See the comments on `process_registered_region_obligations` for the meaning |
224 | // of these fields. | |
8faf50e0 | 225 | delegate: D, |
dc9dc135 XL |
226 | tcx: TyCtxt<'tcx>, |
227 | verify_bound: VerifyBoundCx<'cx, 'tcx>, | |
abe05a73 XL |
228 | } |
229 | ||
8faf50e0 XL |
230 | pub trait TypeOutlivesDelegate<'tcx> { |
231 | fn push_sub_region_constraint( | |
232 | &mut self, | |
233 | origin: SubregionOrigin<'tcx>, | |
234 | a: ty::Region<'tcx>, | |
235 | b: ty::Region<'tcx>, | |
236 | ); | |
237 | ||
238 | fn push_verify( | |
239 | &mut self, | |
240 | origin: SubregionOrigin<'tcx>, | |
241 | kind: GenericKind<'tcx>, | |
242 | a: ty::Region<'tcx>, | |
243 | bound: VerifyBound<'tcx>, | |
244 | ); | |
245 | } | |
246 | ||
dc9dc135 | 247 | impl<'cx, 'tcx, D> TypeOutlives<'cx, 'tcx, D> |
8faf50e0 XL |
248 | where |
249 | D: TypeOutlivesDelegate<'tcx>, | |
250 | { | |
251 | pub fn new( | |
252 | delegate: D, | |
dc9dc135 | 253 | tcx: TyCtxt<'tcx>, |
0bf4aa26 | 254 | region_bound_pairs: &'cx RegionBoundPairs<'tcx>, |
abe05a73 XL |
255 | implicit_region_bound: Option<ty::Region<'tcx>>, |
256 | param_env: ty::ParamEnv<'tcx>, | |
257 | ) -> Self { | |
258 | Self { | |
8faf50e0 XL |
259 | delegate, |
260 | tcx, | |
0bf4aa26 XL |
261 | verify_bound: VerifyBoundCx::new( |
262 | tcx, | |
263 | region_bound_pairs, | |
264 | implicit_region_bound, | |
265 | param_env, | |
266 | ), | |
abe05a73 XL |
267 | } |
268 | } | |
269 | ||
270 | /// Adds constraints to inference such that `T: 'a` holds (or | |
271 | /// reports an error if it cannot). | |
272 | /// | |
273 | /// # Parameters | |
274 | /// | |
275 | /// - `origin`, the reason we need this constraint | |
276 | /// - `ty`, the type `T` | |
277 | /// - `region`, the region `'a` | |
8faf50e0 XL |
278 | pub fn type_must_outlive( |
279 | &mut self, | |
abe05a73 XL |
280 | origin: infer::SubregionOrigin<'tcx>, |
281 | ty: Ty<'tcx>, | |
282 | region: ty::Region<'tcx>, | |
283 | ) { | |
dfeec247 | 284 | debug!("type_must_outlive(ty={:?}, region={:?}, origin={:?})", ty, region, origin); |
abe05a73 | 285 | |
a1dfa0c6 | 286 | assert!(!ty.has_escaping_bound_vars()); |
abe05a73 | 287 | |
a1dfa0c6 XL |
288 | let mut components = smallvec![]; |
289 | self.tcx.push_outlives_components(ty, &mut components); | |
290 | self.components_must_outlive(origin, &components, region); | |
abe05a73 XL |
291 | } |
292 | ||
abe05a73 | 293 | fn components_must_outlive( |
8faf50e0 | 294 | &mut self, |
abe05a73 | 295 | origin: infer::SubregionOrigin<'tcx>, |
a1dfa0c6 | 296 | components: &[Component<'tcx>], |
abe05a73 XL |
297 | region: ty::Region<'tcx>, |
298 | ) { | |
a1dfa0c6 | 299 | for component in components.iter() { |
abe05a73 XL |
300 | let origin = origin.clone(); |
301 | match component { | |
302 | Component::Region(region1) => { | |
dfeec247 | 303 | self.delegate.push_sub_region_constraint(origin, region, region1); |
abe05a73 XL |
304 | } |
305 | Component::Param(param_ty) => { | |
a1dfa0c6 | 306 | self.param_ty_must_outlive(origin, region, *param_ty); |
abe05a73 XL |
307 | } |
308 | Component::Projection(projection_ty) => { | |
a1dfa0c6 | 309 | self.projection_must_outlive(origin, region, *projection_ty); |
abe05a73 XL |
310 | } |
311 | Component::EscapingProjection(subcomponents) => { | |
a1dfa0c6 | 312 | self.components_must_outlive(origin, &subcomponents, region); |
abe05a73 XL |
313 | } |
314 | Component::UnresolvedInferenceVariable(v) => { | |
315 | // ignore this, we presume it will yield an error | |
316 | // later, since if a type variable is not resolved by | |
317 | // this point it never will be | |
8faf50e0 | 318 | self.tcx.sess.delay_span_bug( |
abe05a73 XL |
319 | origin.span(), |
320 | &format!("unresolved inference variable in outlives: {:?}", v), | |
321 | ); | |
322 | } | |
323 | } | |
324 | } | |
325 | } | |
326 | ||
327 | fn param_ty_must_outlive( | |
8faf50e0 | 328 | &mut self, |
abe05a73 XL |
329 | origin: infer::SubregionOrigin<'tcx>, |
330 | region: ty::Region<'tcx>, | |
331 | param_ty: ty::ParamTy, | |
332 | ) { | |
333 | debug!( | |
334 | "param_ty_must_outlive(region={:?}, param_ty={:?}, origin={:?})", | |
8faf50e0 | 335 | region, param_ty, origin |
abe05a73 XL |
336 | ); |
337 | ||
abe05a73 | 338 | let generic = GenericKind::Param(param_ty); |
0bf4aa26 | 339 | let verify_bound = self.verify_bound.generic_bound(generic); |
dfeec247 | 340 | self.delegate.push_verify(origin, generic, region, verify_bound); |
abe05a73 XL |
341 | } |
342 | ||
343 | fn projection_must_outlive( | |
8faf50e0 | 344 | &mut self, |
abe05a73 XL |
345 | origin: infer::SubregionOrigin<'tcx>, |
346 | region: ty::Region<'tcx>, | |
347 | projection_ty: ty::ProjectionTy<'tcx>, | |
348 | ) { | |
349 | debug!( | |
350 | "projection_must_outlive(region={:?}, projection_ty={:?}, origin={:?})", | |
8faf50e0 | 351 | region, projection_ty, origin |
abe05a73 XL |
352 | ); |
353 | ||
354 | // This case is thorny for inference. The fundamental problem is | |
355 | // that there are many cases where we have choice, and inference | |
356 | // doesn't like choice (the current region inference in | |
357 | // particular). :) First off, we have to choose between using the | |
358 | // OutlivesProjectionEnv, OutlivesProjectionTraitDef, and | |
359 | // OutlivesProjectionComponent rules, any one of which is | |
360 | // sufficient. If there are no inference variables involved, it's | |
361 | // not hard to pick the right rule, but if there are, we're in a | |
362 | // bit of a catch 22: if we picked which rule we were going to | |
363 | // use, we could add constraints to the region inference graph | |
364 | // that make it apply, but if we don't add those constraints, the | |
365 | // rule might not apply (but another rule might). For now, we err | |
366 | // on the side of adding too few edges into the graph. | |
367 | ||
13cf67c4 XL |
368 | // Compute the bounds we can derive from the trait definition. |
369 | // These are guaranteed to apply, no matter the inference | |
370 | // results. | |
dfeec247 XL |
371 | let trait_bounds: Vec<_> = |
372 | self.verify_bound.projection_declared_bounds_from_trait(projection_ty).collect(); | |
13cf67c4 | 373 | |
0bf4aa26 XL |
374 | // Compute the bounds we can derive from the environment. This |
375 | // is an "approximate" match -- in some cases, these bounds | |
376 | // may not apply. | |
dfeec247 XL |
377 | let mut approx_env_bounds = |
378 | self.verify_bound.projection_approx_declared_bounds_from_env(projection_ty); | |
379 | debug!("projection_must_outlive: approx_env_bounds={:?}", approx_env_bounds); | |
abe05a73 | 380 | |
13cf67c4 XL |
381 | // Remove outlives bounds that we get from the environment but |
382 | // which are also deducable from the trait. This arises (cc | |
0731742a | 383 | // #55756) in cases where you have e.g., `<T as Foo<'a>>::Item: |
13cf67c4 XL |
384 | // 'a` in the environment but `trait Foo<'b> { type Item: 'b |
385 | // }` in the trait definition. | |
dfeec247 XL |
386 | approx_env_bounds.retain(|bound| match bound.0.kind { |
387 | ty::Projection(projection_ty) => self | |
388 | .verify_bound | |
389 | .projection_declared_bounds_from_trait(projection_ty) | |
390 | .all(|r| r != bound.1), | |
13cf67c4 | 391 | |
dfeec247 | 392 | _ => panic!("expected only projection types from env, not {:?}", bound.0), |
13cf67c4 | 393 | }); |
abe05a73 XL |
394 | |
395 | // If declared bounds list is empty, the only applicable rule is | |
396 | // OutlivesProjectionComponent. If there are inference variables, | |
397 | // then, we can break down the outlives into more primitive | |
398 | // components without adding unnecessary edges. | |
399 | // | |
400 | // If there are *no* inference variables, however, we COULD do | |
401 | // this, but we choose not to, because the error messages are less | |
402 | // good. For example, a requirement like `T::Item: 'r` would be | |
403 | // translated to a requirement that `T: 'r`; when this is reported | |
404 | // to the user, it will thus say "T: 'r must hold so that T::Item: | |
405 | // 'r holds". But that makes it sound like the only way to fix | |
406 | // the problem is to add `T: 'r`, which isn't true. So, if there are no | |
407 | // inference variables, we use a verify constraint instead of adding | |
408 | // edges, which winds up enforcing the same condition. | |
409 | let needs_infer = projection_ty.needs_infer(); | |
0bf4aa26 | 410 | if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer { |
abe05a73 XL |
411 | debug!("projection_must_outlive: no declared bounds"); |
412 | ||
532ac7d7 XL |
413 | for k in projection_ty.substs { |
414 | match k.unpack() { | |
e74abb32 | 415 | GenericArgKind::Lifetime(lt) => { |
532ac7d7 XL |
416 | self.delegate.push_sub_region_constraint(origin.clone(), region, lt); |
417 | } | |
e74abb32 | 418 | GenericArgKind::Type(ty) => { |
532ac7d7 XL |
419 | self.type_must_outlive(origin.clone(), ty, region); |
420 | } | |
e74abb32 | 421 | GenericArgKind::Const(_) => { |
532ac7d7 XL |
422 | // Const parameters don't impose constraints. |
423 | } | |
424 | } | |
abe05a73 XL |
425 | } |
426 | ||
427 | return; | |
428 | } | |
429 | ||
0bf4aa26 XL |
430 | // If we found a unique bound `'b` from the trait, and we |
431 | // found nothing else from the environment, then the best | |
432 | // action is to require that `'b: 'r`, so do that. | |
433 | // | |
434 | // This is best no matter what rule we use: | |
abe05a73 | 435 | // |
0bf4aa26 XL |
436 | // - OutlivesProjectionEnv: these would translate to the requirement that `'b:'r` |
437 | // - OutlivesProjectionTraitDef: these would translate to the requirement that `'b:'r` | |
438 | // - OutlivesProjectionComponent: this would require `'b:'r` | |
439 | // in addition to other conditions | |
440 | if !trait_bounds.is_empty() | |
441 | && trait_bounds[1..] | |
442 | .iter() | |
443 | .chain(approx_env_bounds.iter().map(|b| &b.1)) | |
444 | .all(|b| *b == trait_bounds[0]) | |
445 | { | |
446 | let unique_bound = trait_bounds[0]; | |
dfeec247 | 447 | debug!("projection_must_outlive: unique trait bound = {:?}", unique_bound); |
0bf4aa26 | 448 | debug!("projection_must_outlive: unique declared bound appears in trait ref"); |
dfeec247 | 449 | self.delegate.push_sub_region_constraint(origin, region, unique_bound); |
0bf4aa26 | 450 | return; |
abe05a73 XL |
451 | } |
452 | ||
453 | // Fallback to verifying after the fact that there exists a | |
454 | // declared bound, or that all the components appearing in the | |
455 | // projection outlive; in some cases, this may add insufficient | |
456 | // edges into the inference graph, leading to inference failures | |
457 | // even though a satisfactory solution exists. | |
abe05a73 | 458 | let generic = GenericKind::Projection(projection_ty); |
0bf4aa26 | 459 | let verify_bound = self.verify_bound.generic_bound(generic); |
ba9703b0 | 460 | self.delegate.push_verify(origin, generic, region, verify_bound); |
abe05a73 | 461 | } |
abe05a73 | 462 | } |
8faf50e0 | 463 | |
dc9dc135 | 464 | impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'cx, 'tcx> { |
8faf50e0 XL |
465 | fn push_sub_region_constraint( |
466 | &mut self, | |
467 | origin: SubregionOrigin<'tcx>, | |
468 | a: ty::Region<'tcx>, | |
469 | b: ty::Region<'tcx>, | |
470 | ) { | |
471 | self.sub_regions(origin, a, b) | |
472 | } | |
473 | ||
474 | fn push_verify( | |
475 | &mut self, | |
476 | origin: SubregionOrigin<'tcx>, | |
477 | kind: GenericKind<'tcx>, | |
478 | a: ty::Region<'tcx>, | |
479 | bound: VerifyBound<'tcx>, | |
480 | ) { | |
481 | self.verify_generic_bound(origin, kind, a, bound) | |
482 | } | |
483 | } |