diff options
| author | Camille GILLOT <gillot.camille@gmail.com> | 2020-01-05 23:28:45 +0100 |
|---|---|---|
| committer | Camille GILLOT <gillot.camille@gmail.com> | 2020-01-07 18:08:47 +0100 |
| commit | 86ec4b5f8508854321e9438902bbbcbbcd5d9a7f (patch) | |
| tree | 24eeaeb6140cf31a7904efc33af2aa8b7bc8a453 /src/librustc/infer | |
| parent | 24d09c7c1b454dae43adc39827311d741dcbf896 (diff) | |
| download | rust-86ec4b5f8508854321e9438902bbbcbbcd5d9a7f.tar.gz rust-86ec4b5f8508854321e9438902bbbcbbcd5d9a7f.zip | |
Move required_region_bounds to rustc::infer::opaque_types.
Diffstat (limited to 'src/librustc/infer')
| -rw-r--r-- | src/librustc/infer/opaque_types/mod.rs | 69 |
1 files changed, 67 insertions, 2 deletions
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 10d5fdf30e3..a22ed940961 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -350,7 +350,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!("constrain_opaque_type: bounds={:#?}", bounds); let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs); - let required_region_bounds = tcx.required_region_bounds(opaque_type, bounds.predicates); + let required_region_bounds = + required_region_bounds(tcx, opaque_type, bounds.predicates); debug_assert!(!required_region_bounds.is_empty()); for required_region in required_region_bounds { @@ -1133,7 +1134,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { debug!("instantiate_opaque_types: bounds={:?}", bounds); - let required_region_bounds = tcx.required_region_bounds(ty, bounds.predicates.clone()); + let required_region_bounds = required_region_bounds(tcx, ty, bounds.predicates.clone()); debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds); // Make sure that we are in fact defining the *entire* type @@ -1228,3 +1229,67 @@ pub fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: DefId, opaque_hir_id: hir ); res } + +/// Given a set of predicates that apply to an object type, returns +/// the region bounds that the (erased) `Self` type must +/// outlive. Precisely *because* the `Self` type is erased, the +/// parameter `erased_self_ty` must be supplied to indicate what type +/// has been used to represent `Self` in the predicates +/// themselves. This should really be a unique type; `FreshTy(0)` is a +/// popular choice. +/// +/// N.B., in some cases, particularly around higher-ranked bounds, +/// this function returns a kind of conservative approximation. +/// That is, all regions returned by this function are definitely +/// required, but there may be other region bounds that are not +/// returned, as well as requirements like `for<'a> T: 'a`. +/// +/// Requires that trait definitions have been processed so that we can +/// elaborate predicates and walk supertraits. +// +// FIXME: callers may only have a `&[Predicate]`, not a `Vec`, so that's +// what this code should accept. +crate fn required_region_bounds( + tcx: TyCtxt<'tcx>, + erased_self_ty: Ty<'tcx>, + predicates: Vec<ty::Predicate<'tcx>>, +) -> Vec<ty::Region<'tcx>> { + debug!( + "required_region_bounds(erased_self_ty={:?}, predicates={:?})", + erased_self_ty, predicates + ); + + assert!(!erased_self_ty.has_escaping_bound_vars()); + + traits::elaborate_predicates(tcx, predicates) + .filter_map(|predicate| { + match predicate { + ty::Predicate::Projection(..) + | ty::Predicate::Trait(..) + | ty::Predicate::Subtype(..) + | ty::Predicate::WellFormed(..) + | ty::Predicate::ObjectSafe(..) + | ty::Predicate::ClosureKind(..) + | ty::Predicate::RegionOutlives(..) + | ty::Predicate::ConstEvaluatable(..) => None, + ty::Predicate::TypeOutlives(predicate) => { + // Search for a bound of the form `erased_self_ty + // : 'a`, but be wary of something like `for<'a> + // erased_self_ty : 'a` (we interpret a + // higher-ranked bound like that as 'static, + // though at present the code in `fulfill.rs` + // considers such bounds to be unsatisfiable, so + // it's kind of a moot point since you could never + // construct such an object, but this seems + // correct even if that code changes). + let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder(); + if t == &erased_self_ty && !r.has_escaping_bound_vars() { + Some(*r) + } else { + None + } + } + } + }) + .collect() +} |
