|
10 | 10 |
|
11 | 11 | use middle::free_region::FreeRegionMap;
|
12 | 12 | use infer::{InferCtxt, GenericKind};
|
13 |
| -use traits::FulfillmentContext; |
14 |
| -use ty::{self, Ty, TypeFoldable}; |
15 |
| -use ty::outlives::Component; |
16 |
| -use ty::wf; |
| 13 | +use infer::outlives::implied_bounds::ImpliedBound; |
| 14 | +use ty::{self, Ty}; |
17 | 15 |
|
18 | 16 | use syntax::ast;
|
19 | 17 | use syntax_pos::Span;
|
@@ -44,24 +42,6 @@ pub struct OutlivesEnvironment<'tcx> {
|
44 | 42 | region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
|
45 | 43 | }
|
46 | 44 |
|
47 |
| -/// Implied bounds are region relationships that we deduce |
48 |
| -/// automatically. The idea is that (e.g.) a caller must check that a |
49 |
| -/// function's argument types are well-formed immediately before |
50 |
| -/// calling that fn, and hence the *callee* can assume that its |
51 |
| -/// argument types are well-formed. This may imply certain relationships |
52 |
| -/// between generic parameters. For example: |
53 |
| -/// |
54 |
| -/// fn foo<'a,T>(x: &'a T) |
55 |
| -/// |
56 |
| -/// can only be called with a `'a` and `T` such that `&'a T` is WF. |
57 |
| -/// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`. |
58 |
| -#[derive(Debug)] |
59 |
| -enum ImpliedBound<'tcx> { |
60 |
| - RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), |
61 |
| - RegionSubParam(ty::Region<'tcx>, ty::ParamTy), |
62 |
| - RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>), |
63 |
| -} |
64 |
| - |
65 | 45 | impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
|
66 | 46 | pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
|
67 | 47 | let mut free_region_map = FreeRegionMap::new();
|
@@ -163,7 +143,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
|
163 | 143 | for &ty in fn_sig_tys {
|
164 | 144 | let ty = infcx.resolve_type_vars_if_possible(&ty);
|
165 | 145 | debug!("add_implied_bounds: ty = {}", ty);
|
166 |
| - let implied_bounds = self.implied_bounds(infcx, body_id, ty, span); |
| 146 | + let implied_bounds = infcx.implied_bounds(self.param_env, body_id, ty, span); |
167 | 147 |
|
168 | 148 | // But also record other relationships, such as `T:'x`,
|
169 | 149 | // that don't go into the free-region-map but which we use
|
@@ -203,153 +183,4 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
|
203 | 183 | }
|
204 | 184 | }
|
205 | 185 | }
|
206 |
| - |
207 |
| - /// Compute the implied bounds that a callee/impl can assume based on |
208 |
| - /// the fact that caller/projector has ensured that `ty` is WF. See |
209 |
| - /// the `ImpliedBound` type for more details. |
210 |
| - fn implied_bounds( |
211 |
| - &mut self, |
212 |
| - infcx: &InferCtxt<'a, 'gcx, 'tcx>, |
213 |
| - body_id: ast::NodeId, |
214 |
| - ty: Ty<'tcx>, |
215 |
| - span: Span, |
216 |
| - ) -> Vec<ImpliedBound<'tcx>> { |
217 |
| - let tcx = infcx.tcx; |
218 |
| - |
219 |
| - // Sometimes when we ask what it takes for T: WF, we get back that |
220 |
| - // U: WF is required; in that case, we push U onto this stack and |
221 |
| - // process it next. Currently (at least) these resulting |
222 |
| - // predicates are always guaranteed to be a subset of the original |
223 |
| - // type, so we need not fear non-termination. |
224 |
| - let mut wf_types = vec![ty]; |
225 |
| - |
226 |
| - let mut implied_bounds = vec![]; |
227 |
| - |
228 |
| - let mut fulfill_cx = FulfillmentContext::new(); |
229 |
| - |
230 |
| - while let Some(ty) = wf_types.pop() { |
231 |
| - // Compute the obligations for `ty` to be well-formed. If `ty` is |
232 |
| - // an unresolved inference variable, just substituted an empty set |
233 |
| - // -- because the return type here is going to be things we *add* |
234 |
| - // to the environment, it's always ok for this set to be smaller |
235 |
| - // than the ultimate set. (Note: normally there won't be |
236 |
| - // unresolved inference variables here anyway, but there might be |
237 |
| - // during typeck under some circumstances.) |
238 |
| - let obligations = |
239 |
| - wf::obligations(infcx, self.param_env, body_id, ty, span).unwrap_or(vec![]); |
240 |
| - |
241 |
| - // NB: All of these predicates *ought* to be easily proven |
242 |
| - // true. In fact, their correctness is (mostly) implied by |
243 |
| - // other parts of the program. However, in #42552, we had |
244 |
| - // an annoying scenario where: |
245 |
| - // |
246 |
| - // - Some `T::Foo` gets normalized, resulting in a |
247 |
| - // variable `_1` and a `T: Trait<Foo=_1>` constraint |
248 |
| - // (not sure why it couldn't immediately get |
249 |
| - // solved). This result of `_1` got cached. |
250 |
| - // - These obligations were dropped on the floor here, |
251 |
| - // rather than being registered. |
252 |
| - // - Then later we would get a request to normalize |
253 |
| - // `T::Foo` which would result in `_1` being used from |
254 |
| - // the cache, but hence without the `T: Trait<Foo=_1>` |
255 |
| - // constraint. As a result, `_1` never gets resolved, |
256 |
| - // and we get an ICE (in dropck). |
257 |
| - // |
258 |
| - // Therefore, we register any predicates involving |
259 |
| - // inference variables. We restrict ourselves to those |
260 |
| - // involving inference variables both for efficiency and |
261 |
| - // to avoids duplicate errors that otherwise show up. |
262 |
| - fulfill_cx.register_predicate_obligations( |
263 |
| - infcx, |
264 |
| - obligations |
265 |
| - .iter() |
266 |
| - .filter(|o| o.predicate.has_infer_types()) |
267 |
| - .cloned()); |
268 |
| - |
269 |
| - // From the full set of obligations, just filter down to the |
270 |
| - // region relationships. |
271 |
| - implied_bounds.extend(obligations.into_iter().flat_map(|obligation| { |
272 |
| - assert!(!obligation.has_escaping_regions()); |
273 |
| - match obligation.predicate { |
274 |
| - ty::Predicate::Trait(..) | |
275 |
| - ty::Predicate::Equate(..) | |
276 |
| - ty::Predicate::Subtype(..) | |
277 |
| - ty::Predicate::Projection(..) | |
278 |
| - ty::Predicate::ClosureKind(..) | |
279 |
| - ty::Predicate::ObjectSafe(..) | |
280 |
| - ty::Predicate::ConstEvaluatable(..) => vec![], |
281 |
| - |
282 |
| - ty::Predicate::WellFormed(subty) => { |
283 |
| - wf_types.push(subty); |
284 |
| - vec![] |
285 |
| - } |
286 |
| - |
287 |
| - ty::Predicate::RegionOutlives(ref data) => { |
288 |
| - match tcx.no_late_bound_regions(data) { |
289 |
| - None => vec![], |
290 |
| - Some(ty::OutlivesPredicate(r_a, r_b)) => { |
291 |
| - vec![ImpliedBound::RegionSubRegion(r_b, r_a)] |
292 |
| - } |
293 |
| - } |
294 |
| - } |
295 |
| - |
296 |
| - ty::Predicate::TypeOutlives(ref data) => { |
297 |
| - match tcx.no_late_bound_regions(data) { |
298 |
| - None => vec![], |
299 |
| - Some(ty::OutlivesPredicate(ty_a, r_b)) => { |
300 |
| - let ty_a = infcx.resolve_type_vars_if_possible(&ty_a); |
301 |
| - let components = tcx.outlives_components(ty_a); |
302 |
| - self.implied_bounds_from_components(r_b, components) |
303 |
| - } |
304 |
| - } |
305 |
| - } |
306 |
| - } |
307 |
| - })); |
308 |
| - } |
309 |
| - |
310 |
| - // Ensure that those obligations that we had to solve |
311 |
| - // get solved *here*. |
312 |
| - match fulfill_cx.select_all_or_error(infcx) { |
313 |
| - Ok(()) => (), |
314 |
| - Err(errors) => infcx.report_fulfillment_errors(&errors, None), |
315 |
| - } |
316 |
| - |
317 |
| - implied_bounds |
318 |
| - } |
319 |
| - |
320 |
| - /// When we have an implied bound that `T: 'a`, we can further break |
321 |
| - /// this down to determine what relationships would have to hold for |
322 |
| - /// `T: 'a` to hold. We get to assume that the caller has validated |
323 |
| - /// those relationships. |
324 |
| - fn implied_bounds_from_components( |
325 |
| - &self, |
326 |
| - sub_region: ty::Region<'tcx>, |
327 |
| - sup_components: Vec<Component<'tcx>>, |
328 |
| - ) -> Vec<ImpliedBound<'tcx>> { |
329 |
| - sup_components |
330 |
| - .into_iter() |
331 |
| - .flat_map(|component| { |
332 |
| - match component { |
333 |
| - Component::Region(r) => |
334 |
| - vec![ImpliedBound::RegionSubRegion(sub_region, r)], |
335 |
| - Component::Param(p) => |
336 |
| - vec![ImpliedBound::RegionSubParam(sub_region, p)], |
337 |
| - Component::Projection(p) => |
338 |
| - vec![ImpliedBound::RegionSubProjection(sub_region, p)], |
339 |
| - Component::EscapingProjection(_) => |
340 |
| - // If the projection has escaping regions, don't |
341 |
| - // try to infer any implied bounds even for its |
342 |
| - // free components. This is conservative, because |
343 |
| - // the caller will still have to prove that those |
344 |
| - // free components outlive `sub_region`. But the |
345 |
| - // idea is that the WAY that the caller proves |
346 |
| - // that may change in the future and we want to |
347 |
| - // give ourselves room to get smarter here. |
348 |
| - vec![], |
349 |
| - Component::UnresolvedInferenceVariable(..) => |
350 |
| - vec![], |
351 |
| - } |
352 |
| - }) |
353 |
| - .collect() |
354 |
| - } |
355 | 186 | }
|
0 commit comments