diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 71a57dbf32fb1..7b2cfa0a3ffec 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -870,6 +870,7 @@ for ty::steal::Steal impl_stable_hash_for!(struct ty::ParamEnv<'tcx> { caller_bounds, + universe, reveal }); @@ -1039,3 +1040,12 @@ for traits::VtableGeneratorData<'gcx, N> where N: HashStable HashStable> +for ty::UniverseIndex { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + self.depth().hash_stable(hcx, hasher); + } +} diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 027ad4174bd15..76d3c7f150670 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -546,7 +546,8 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, predicates); let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates), - unnormalized_env.reveal); + unnormalized_env.reveal, + unnormalized_env.universe); tcx.infer_ctxt().enter(|infcx| { // FIXME. We should really... do something with these region @@ -620,7 +621,9 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("normalize_param_env_or_error: resolved predicates={:?}", predicates); - ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal) + ty::ParamEnv::new(tcx.intern_predicates(&predicates), + unnormalized_env.reveal, + unnormalized_env.universe) }) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 26fcd5c311056..856c53d19c98c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1348,9 +1348,7 @@ pub struct UniverseIndex(u32); impl UniverseIndex { /// The root universe, where things that the user defined are /// visible. - pub fn root() -> UniverseIndex { - UniverseIndex(0) - } + pub const ROOT: UniverseIndex = UniverseIndex(0); /// A "subuniverse" corresponds to being inside a `forall` quantifier. /// So, for example, suppose we have this type in universe `U`: @@ -1366,6 +1364,13 @@ impl UniverseIndex { pub fn subuniverse(self) -> UniverseIndex { UniverseIndex(self.0 + 1) } + + /// Gets the "depth" of this universe in the universe tree. This + /// is not really useful except for e.g. the `HashStable` + /// implementation + pub fn depth(&self) -> u32 { + self.0 + } } /// When type checking, we use the `ParamEnv` to track @@ -1382,6 +1387,17 @@ pub struct ParamEnv<'tcx> { /// want `Reveal::All` -- note that this is always paired with an /// empty environment. To get that, use `ParamEnv::reveal()`. pub reveal: traits::Reveal, + + /// What is the innermost universe we have created? Starts out as + /// `UniverseIndex::root()` but grows from there as we enter + /// universal quantifiers. + /// + /// NB: At present, we exclude the universal quantifiers on the + /// item we are type-checking, and just consider those names as + /// part of the root universe. So this would only get incremented + /// when we enter into a higher-ranked (`for<..>`) type or trait + /// bound. + pub universe: UniverseIndex, } impl<'tcx> ParamEnv<'tcx> { @@ -2657,7 +2673,8 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // sure that this will succeed without errors anyway. let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates), - traits::Reveal::UserFacing); + traits::Reveal::UserFacing, + ty::UniverseIndex::ROOT); let body_id = tcx.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| { tcx.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 0dc1338fff860..3a1ad8db9c20a 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -405,6 +405,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> { tcx.lift(&self.caller_bounds).map(|caller_bounds| { ty::ParamEnv { reveal: self.reveal, + universe: self.universe, caller_bounds, } }) @@ -733,8 +734,29 @@ impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { } } -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::ParamEnv<'tcx> { reveal, caller_bounds } +impl<'tcx> TypeFoldable<'tcx> for ty::ParamEnv<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + ty::ParamEnv { + reveal: self.reveal, + caller_bounds: self.caller_bounds.fold_with(folder), + universe: self.universe.fold_with(folder), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + let &ty::ParamEnv { reveal: _, ref universe, ref caller_bounds } = self; + universe.super_visit_with(visitor) || caller_bounds.super_visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable<'tcx> for ty::UniverseIndex { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self { + *self + } + + fn super_visit_with>(&self, _visitor: &mut V) -> bool { + false + } } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice> { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 110808919e905..44771444c8aa8 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -153,14 +153,15 @@ impl<'tcx> ty::ParamEnv<'tcx> { /// Construct a trait environment suitable for contexts where /// there are no where clauses in scope. pub fn empty(reveal: Reveal) -> Self { - Self::new(ty::Slice::empty(), reveal) + Self::new(ty::Slice::empty(), reveal, ty::UniverseIndex::ROOT) } /// Construct a trait environment with the given set of predicates. pub fn new(caller_bounds: &'tcx ty::Slice>, - reveal: Reveal) + reveal: Reveal, + universe: ty::UniverseIndex) -> Self { - ty::ParamEnv { caller_bounds, reveal } + ty::ParamEnv { caller_bounds, reveal, universe } } /// Returns a new parameter environment with the same clauses, but diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 4c10f28eb8e5d..d0419382bc312 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -218,7 +218,8 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // the new hybrid bounds we computed. let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id); let param_env = ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), - Reveal::UserFacing); + Reveal::UserFacing, + ty::UniverseIndex::ROOT); let param_env = traits::normalize_param_env_or_error(tcx, impl_m.def_id, param_env,