From 86ec4b5f8508854321e9438902bbbcbbcd5d9a7f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 5 Jan 2020 23:28:45 +0100 Subject: [PATCH] Move required_region_bounds to rustc::infer::opaque_types. --- src/librustc/infer/opaque_types/mod.rs | 69 +++++++++++++++++++++++++- src/librustc/traits/wf.rs | 5 +- src/librustc/ty/util.rs | 64 ------------------------ 3 files changed, 70 insertions(+), 68 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 10d5fdf30e3ec..a22ed94096132 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>, +) -> Vec> { + 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() +} diff --git a/src/librustc/traits/wf.rs b/src/librustc/traits/wf.rs index d033ab60f15db..551f8fde12b18 100644 --- a/src/librustc/traits/wf.rs +++ b/src/librustc/traits/wf.rs @@ -1,3 +1,4 @@ +use crate::infer::opaque_types::required_region_bounds; use crate::infer::InferCtxt; use crate::middle::lang_items; use crate::traits::{self, AssocTypeBoundData}; @@ -668,7 +669,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { /// from the declarations of `SomeTrait`, `Send`, and friends -- if /// they declare `trait SomeTrait : 'static`, for example, then /// `'static` would appear in the list. The hard work is done by -/// `ty::required_region_bounds`, see that for more information. +/// `infer::required_region_bounds`, see that for more information. pub fn object_region_bounds<'tcx>( tcx: TyCtxt<'tcx>, existential_predicates: ty::Binder<&'tcx ty::List>>, @@ -689,7 +690,7 @@ pub fn object_region_bounds<'tcx>( }) .collect(); - tcx.required_region_bounds(open_ty, predicates) + required_region_bounds(tcx, open_ty, predicates) } /// Find the span of a generic bound affecting an associated type. diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index e0f4f2616017d..ee99176dc47f5 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -393,70 +393,6 @@ impl<'tcx> TyCtxt<'tcx> { (a, b) } - /// 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. - pub fn required_region_bounds( - self, - erased_self_ty: Ty<'tcx>, - predicates: Vec>, - ) -> Vec> { - debug!( - "required_region_bounds(erased_self_ty={:?}, predicates={:?})", - erased_self_ty, predicates - ); - - assert!(!erased_self_ty.has_escaping_bound_vars()); - - traits::elaborate_predicates(self, 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() - } - /// Calculate the destructor of a given type. pub fn calculate_dtor( self,