From 1003b7f85e75e3a726adc34b9c315e98094176d5 Mon Sep 17 00:00:00 2001 From: scalexm Date: Mon, 22 Oct 2018 20:37:56 +0200 Subject: [PATCH 01/11] Move `BoundTy` to `ty::TyKind` --- src/librustc/ich/impls_ty.rs | 4 ++- src/librustc/infer/canonical/canonicalizer.rs | 21 +++++------- .../infer/canonical/query_response.rs | 2 +- src/librustc/infer/canonical/substitute.rs | 3 +- src/librustc/infer/freshen.rs | 4 +-- src/librustc/traits/coherence.rs | 2 +- src/librustc/traits/error_reporting.rs | 2 +- src/librustc/traits/query/dropck_outlives.rs | 1 + src/librustc/traits/select.rs | 6 ++-- src/librustc/ty/context.rs | 2 +- src/librustc/ty/error.rs | 2 +- src/librustc/ty/fast_reject.rs | 2 +- src/librustc/ty/flags.rs | 5 +-- src/librustc/ty/item_path.rs | 1 + src/librustc/ty/layout.rs | 9 ++++-- src/librustc/ty/mod.rs | 3 +- src/librustc/ty/outlives.rs | 1 + src/librustc/ty/structural_impls.rs | 32 +++++++++++++++---- src/librustc/ty/sty.rs | 30 ++++++++++++++--- src/librustc/ty/subst.rs | 2 +- src/librustc/ty/util.rs | 2 +- src/librustc/ty/walk.rs | 2 +- src/librustc/ty/wf.rs | 1 + src/librustc/util/ppaux.rs | 17 ++++++++-- .../debuginfo/type_names.rs | 1 + src/librustc_lint/types.rs | 1 + src/librustc_mir/monomorphize/item.rs | 1 + src/librustc_traits/chalk_context.rs | 1 + src/librustc_traits/dropck_outlives.rs | 2 +- src/librustc_traits/lowering/environment.rs | 1 + src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/variance/constraints.rs | 1 + src/librustdoc/clean/mod.rs | 1 + 33 files changed, 116 insertions(+), 51 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 0c93b86ee4d11..5873dd2eab7d6 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -852,6 +852,9 @@ for ty::TyKind<'gcx> Param(param_ty) => { param_ty.hash_stable(hcx, hasher); } + Bound(bound_ty) => { + bound_ty.hash_stable(hcx, hasher); + } Foreign(def_id) => { def_id.hash_stable(hcx, hasher); } @@ -869,7 +872,6 @@ impl_stable_hash_for!(enum ty::InferTy { FreshTy(a), FreshIntTy(a), FreshFloatTy(a), - BoundTy(a), }); impl<'a, 'gcx> HashStable> diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index cc6e4df071033..a7634b8bd2a7a 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -337,8 +337,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> bug!("encountered a fresh type during canonicalization") } - ty::Infer(ty::BoundTy(_)) => { - bug!("encountered a canonical type during canonicalization") + ty::Bound(_) => { + bug!("encountered a bound type during canonicalization") } ty::Closure(..) @@ -455,7 +455,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { /// or returns an existing variable if `kind` has already been /// seen. `kind` is expected to be an unbound variable (or /// potentially a free region). - fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTy { + fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTyIndex { let Canonicalizer { variables, query_state, @@ -506,10 +506,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { }) }; - BoundTy { - level: ty::INNERMOST, - var, - } + var } /// Shorthand helper that creates a canonical region variable for @@ -552,9 +549,8 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { info: CanonicalVarInfo, r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { - let b = self.canonical_var(info, r.into()); - debug_assert_eq!(ty::INNERMOST, b.level); - self.tcx().mk_region(ty::ReCanonical(b.var)) + let var = self.canonical_var(info, r.into()); + self.tcx().mk_region(ty::ReCanonical(var)) } /// Given a type variable `ty_var` of the given kind, first check @@ -570,9 +566,8 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { let info = CanonicalVarInfo { kind: CanonicalVarKind::Ty(ty_kind), }; - let b = self.canonical_var(info, ty_var.into()); - debug_assert_eq!(ty::INNERMOST, b.level); - self.tcx().mk_infer(ty::InferTy::BoundTy(b)) + let var = self.canonical_var(info, ty_var.into()); + self.tcx().mk_ty(ty::Bound(BoundTy::new(ty::INNERMOST, var))) } } } diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index b3ce5eb7e56c2..27ee33a452ef8 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -432,7 +432,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { match result_value.unpack() { UnpackedKind::Type(result_value) => { // e.g., here `result_value` might be `?0` in the example above... - if let ty::Infer(ty::InferTy::BoundTy(b)) = result_value.sty { + if let ty::Bound(b) = result_value.sty { // in which case we would set `canonical_vars[0]` to `Some(?U)`. opt_values[b.var] = Some(*original_value); } diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs index 03441c3dee35e..80a2497bbf613 100644 --- a/src/librustc/infer/canonical/substitute.rs +++ b/src/librustc/infer/canonical/substitute.rs @@ -85,8 +85,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match t.sty { - ty::Infer(ty::InferTy::BoundTy(b)) => { - debug_assert_eq!(ty::INNERMOST, b.level); + ty::Bound(b) => { match self.var_values.var_values[b.var].unpack() { UnpackedKind::Type(ty) => ty, r => bug!("{:?} is a type but value is {:?}", b, r), diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 1647f259db9fb..c12e64b4c2c59 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -171,8 +171,8 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { t } - ty::Infer(ty::BoundTy(..)) => - bug!("encountered canonical ty during freshening"), + ty::Bound(..) => + bug!("encountered bound ty during freshening"), ty::Generator(..) | ty::Bool | diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 817e9ffcbb55d..71b77909b82a8 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -455,7 +455,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool { false } - ty::Infer(..) => match in_crate { + ty::Bound(..) | ty::Infer(..) => match in_crate { InCrate::Local => false, // The inference variable might be unified with a local // type in that remote crate. diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 18ee98c515fb2..e6ae0557c33af 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::Generator(..) => Some(18), ty::Foreign(..) => Some(19), ty::GeneratorWitness(..) => Some(20), - ty::Infer(..) | ty::Error => None, + ty::Bound(..) | ty::Infer(..) | ty::Error => None, ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), } } diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index 8f7b0df8b95aa..62317f074764f 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -252,6 +252,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> | ty::Param(_) | ty::Opaque(..) | ty::Infer(_) + | ty::Bound(..) | ty::Generator(..) => false, ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index ce515c4507772..691c9d9da49bc 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2445,7 +2445,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::Infer(ty::TyVar(_)) => Ambiguous, ty::UnnormalizedProjection(..) - | ty::Infer(ty::BoundTy(_)) + | ty::Bound(_) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) => { @@ -2530,7 +2530,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } ty::UnnormalizedProjection(..) - | ty::Infer(ty::BoundTy(_)) + | ty::Bound(_) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) => { @@ -2573,7 +2573,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { | ty::Param(..) | ty::Foreign(..) | ty::Projection(..) - | ty::Infer(ty::BoundTy(_)) + | ty::Bound(_) | ty::Infer(ty::TyVar(_)) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 409665e477745..05d9d4bc37d79 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2243,7 +2243,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { sty_debug_print!( self, Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr, - Generator, GeneratorWitness, Dynamic, Closure, Tuple, + Generator, GeneratorWitness, Dynamic, Closure, Tuple, Bound, Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign); println!("Substs interner: #{}", self.interners.substs.borrow().len()); diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 855983042c026..4737c72b1ef0f 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -212,7 +212,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::Infer(ty::TyVar(_)) => "inferred type".into(), ty::Infer(ty::IntVar(_)) => "integral variable".into(), ty::Infer(ty::FloatVar(_)) => "floating-point variable".into(), - ty::Infer(ty::BoundTy(_)) | + ty::Bound(_) | ty::Infer(ty::FreshTy(_)) => "fresh type".into(), ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(), ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(), diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index e6aaf8b1bb206..380f95993f8fb 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -122,7 +122,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::Foreign(def_id) => { Some(ForeignSimplifiedType(def_id)) } - ty::Infer(_) | ty::Error => None, + ty::Bound(..) | ty::Infer(_) | ty::Error => None, } } diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index a7b21688fbeb3..92e08878708f6 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -115,14 +115,15 @@ impl FlagComputation { self.add_substs(&substs.substs); } + &ty::Bound(_) => self.add_flags(TypeFlags::HAS_CANONICAL_VARS), + &ty::Infer(infer) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right? self.add_flags(TypeFlags::HAS_TY_INFER); match infer { ty::FreshTy(_) | ty::FreshIntTy(_) | - ty::FreshFloatTy(_) | - ty::BoundTy(_) => { + ty::FreshFloatTy(_) => { self.add_flags(TypeFlags::HAS_CANONICAL_VARS); } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 7153c729d1542..d44ba03084159 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -519,6 +519,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { ty::Param(_) | ty::Opaque(..) | ty::Infer(_) | + ty::Bound(..) | ty::Error | ty::GeneratorWitness(..) | ty::Never | diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 05d4aeb6ddec4..5500572161735 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1124,9 +1124,14 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } tcx.layout_raw(param_env.and(normalized))? } - ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | ty::Infer(_) => { + + ty::Bound(..) | + ty::UnnormalizedProjection(..) | + ty::GeneratorWitness(..) | + ty::Infer(_) => { bug!("LayoutDetails::compute: unexpected type `{}`", ty) } + ty::Param(_) | ty::Error => { return Err(LayoutError::Unknown(ty)); } @@ -1703,7 +1708,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } } - ty::Projection(_) | ty::UnnormalizedProjection(..) | + ty::Projection(_) | ty::UnnormalizedProjection(..) | ty::Bound(..) | ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error => { bug!("TyLayout::field_type: unexpected type `{}`", this.ty) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index ad26383df6ac2..6ce65177442dc 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -63,7 +63,7 @@ use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, use hir; -pub use self::sty::{Binder, BoundTy, BoundTyIndex, DebruijnIndex, INNERMOST}; +pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundTyIndex, DebruijnIndex, INNERMOST}; pub use self::sty::{FnSig, GenSig, CanonicalPolyFnSig, PolyFnSig, PolyGenSig}; pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut}; @@ -2378,6 +2378,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } + Bound(..) | Infer(..) => { bug!("unexpected type `{:?}` in sized_constraint_for_ty", ty) diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index b49664b624733..4c820447be234 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -156,6 +156,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::FnDef(..) | // OutlivesFunction (*) ty::FnPtr(_) | // OutlivesFunction (*) ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*) + ty::Bound(..) | ty::Error => { // (*) Bare functions and traits are both binders. In the // RFC, this means we would add the bound regions to the diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 05f5f923557ec..59a66513eef05 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -734,9 +734,19 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::UnnormalizedProjection(data.fold_with(folder)) } ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)), - ty::Bool | ty::Char | ty::Str | ty::Int(_) | - ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) | - ty::Param(..) | ty::Never | ty::Foreign(..) => return self + + ty::Bool | + ty::Char | + ty::Str | + ty::Int(_) | + ty::Uint(_) | + ty::Float(_) | + ty::Error | + ty::Infer(_) | + ty::Param(..) | + ty::Bound(..) | + ty::Never | + ty::Foreign(..) => return self }; if self.sty == sty { @@ -771,9 +781,19 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { data.visit_with(visitor) } ty::Opaque(_, ref substs) => substs.visit_with(visitor), - ty::Bool | ty::Char | ty::Str | ty::Int(_) | - ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) | - ty::Param(..) | ty::Never | ty::Foreign(..) => false, + + ty::Bool | + ty::Char | + ty::Str | + ty::Int(_) | + ty::Uint(_) | + ty::Float(_) | + ty::Error | + ty::Infer(_) | + ty::Bound(..) | + ty::Param(..) | + ty::Never | + ty::Foreign(..) => false, } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 62e38ad9bfa66..25f7496e8931c 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -188,6 +188,9 @@ pub enum TyKind<'tcx> { /// A type parameter; for example, `T` in `fn f(x: T) {} Param(ParamTy), + /// Bound type variable, used only when preparing a trait query. + Bound(BoundTy), + /// A type variable used during type checking. Infer(InferTy), @@ -1219,9 +1222,6 @@ pub enum InferTy { FreshTy(u32), FreshIntTy(u32), FreshFloatTy(u32), - - /// Bound type variable, used only when preparing a trait query. - BoundTy(BoundTy), } newtype_index! { @@ -1232,9 +1232,28 @@ newtype_index! { pub struct BoundTy { pub level: DebruijnIndex, pub var: BoundTyIndex, + pub kind: BoundTyKind, } -impl_stable_hash_for!(struct BoundTy { level, var }); +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] +pub enum BoundTyKind { + Anon, + Param(InternedString), +} + +impl_stable_hash_for!(struct BoundTy { level, var, kind }); +impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) }); + +impl BoundTy { + pub fn new(level: DebruijnIndex, var: BoundTyIndex) -> Self { + debug_assert_eq!(ty::INNERMOST, level); + BoundTy { + level, + var, + kind: BoundTyKind::Anon, + } + } +} /// A `ProjectionPredicate` for an `ExistentialTraitRef`. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] @@ -1865,6 +1884,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { Tuple(..) | Foreign(..) | Param(_) | + Bound(..) | Infer(_) | Error => { vec![] @@ -1930,7 +1950,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { ty::Infer(ty::TyVar(_)) => false, - ty::Infer(ty::BoundTy(_)) | + ty::Bound(_) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) => diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 02b5d36ecce6e..87c2c9b6005aa 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -556,7 +556,7 @@ impl CanonicalUserSubsts<'tcx> { self.value.substs.iter().zip(BoundTyIndex::new(0)..).all(|(kind, cvar)| { match kind.unpack() { UnpackedKind::Type(ty) => match ty.sty { - ty::Infer(ty::BoundTy(ref b)) => cvar == b.var, + ty::Bound(ref b) => cvar == b.var, _ => false, }, diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 00a1bfaacd781..0a758285a29b1 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -951,7 +951,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Can refer to a type which may drop. // FIXME(eddyb) check this against a ParamEnv. - ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) | + ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) | ty::Bound(..) | ty::Opaque(..) | ty::Infer(_) | ty::Error => true, ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 47fbfba87748b..284c595ee2d96 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -82,7 +82,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { match parent_ty.sty { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Infer(_) | ty::Param(_) | ty::Never | ty::Error | - ty::Foreign(..) => { + ty::Bound(..) | ty::Foreign(..) => { } ty::Array(ty, len) => { push_const(stack, len); diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 27747970f76b2..eb97f1177af1b 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -258,6 +258,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { ty::GeneratorWitness(..) | ty::Never | ty::Param(_) | + ty::Bound(..) | ty::Foreign(..) => { // WfScalar, WfParameter, etc } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index abdd7fd8d40bf..320fee5638e2d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -16,7 +16,7 @@ use ty::subst::{self, Subst}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{Bool, Char, Adt}; use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; -use ty::{Param, RawPtr, Ref, Never, Tuple}; +use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use ty::{UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; @@ -976,7 +976,6 @@ define_print! { ty::TyVar(_) => write!(f, "_"), ty::IntVar(_) => write!(f, "{}", "{integer}"), ty::FloatVar(_) => write!(f, "{}", "{float}"), - ty::BoundTy(_) => write!(f, "_"), ty::FreshTy(v) => write!(f, "FreshTy({})", v), ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v), ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v) @@ -988,7 +987,6 @@ define_print! { ty::TyVar(ref v) => write!(f, "{:?}", v), ty::IntVar(ref v) => write!(f, "{:?}", v), ty::FloatVar(ref v) => write!(f, "{:?}", v), - ty::BoundTy(v) => write!(f, "?{:?}", v.var.index()), ty::FreshTy(v) => write!(f, "FreshTy({:?})", v), ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v), ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v) @@ -1119,6 +1117,19 @@ define_print! { Infer(infer_ty) => write!(f, "{}", infer_ty), Error => write!(f, "[type error]"), Param(ref param_ty) => write!(f, "{}", param_ty), + Bound(bound_ty) => { + match bound_ty.kind { + ty::BoundTyKind::Anon => { + if bound_ty.level == ty::INNERMOST { + write!(f, "?{}", bound_ty.var.index()) + } else { + write!(f, "?{}_{}", bound_ty.level.index(), bound_ty.var.index()) + } + } + + ty::BoundTyKind::Param(p) => write!(f, "{}", p), + } + } Adt(def, substs) => cx.parameterized(f, substs, def.did, &[]), Dynamic(data, r) => { let r = r.print_to_string(cx); diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs index f5abb527e430f..eb5ae81b21840 100644 --- a/src/librustc_codegen_llvm/debuginfo/type_names.rs +++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs @@ -173,6 +173,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ty::Infer(_) | ty::UnnormalizedProjection(..) | ty::Projection(..) | + ty::Bound(..) | ty::Opaque(..) | ty::GeneratorWitness(..) | ty::Param(_) => { diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 5197876f92197..2e19b441d0e39 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -718,6 +718,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Param(..) | ty::Infer(..) | + ty::Bound(..) | ty::Error | ty::Closure(..) | ty::Generator(..) | diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 4c4d56c893838..9d69a5669b1c0 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -382,6 +382,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { self.push_type_params(substs, iter::empty(), output); } ty::Error | + ty::Bound(..) | ty::Infer(_) | ty::UnnormalizedProjection(..) | ty::Projection(..) | diff --git a/src/librustc_traits/chalk_context.rs b/src/librustc_traits/chalk_context.rs index 5d6badf120286..bf252053199f8 100644 --- a/src/librustc_traits/chalk_context.rs +++ b/src/librustc_traits/chalk_context.rs @@ -506,6 +506,7 @@ impl context::UnificationOps, ChalkArenas<'tcx>> ty::GeneratorWitness(..) | ty::UnnormalizedProjection(..) | ty::Infer(..) | + ty::Bound(..) | ty::Error => { bug!("unexpected type {:?}", ty) } diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 2ad7ab7c4d927..af64522f18398 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -274,7 +274,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>( ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), - ty::Infer(..) | ty::Error => { + ty::Bound(..) | ty::Infer(..) | ty::Error => { // By the time this code runs, all type variables ought to // be fully resolved. Err(NoSolution) diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index c71898f73ecad..052ca37b31371 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -93,6 +93,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> { ty::GeneratorWitness(..) | ty::UnnormalizedProjection(..) | ty::Infer(..) | + ty::Bound(..) | ty::Error => { bug!("unexpected type {:?}", ty); } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index e0ee26cba0828..3f0a353124442 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -128,7 +128,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)), ty::Param(ref p) => Some(PointerKind::OfParam(p)), // Insufficient type information. - ty::Infer(_) => None, + ty::Bound(..) | ty::Infer(_) => None, ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | ty::Float(_) | ty::Array(..) | ty::GeneratorWitness(..) | diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 3e523c0c7f559..b11b034ee13cc 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -338,6 +338,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | + ty::Bound(..) | ty::Infer(..) => { bug!("unexpected type encountered in \ variance inference: {}", diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 88240e844edc2..8391db9a37d50 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2733,6 +2733,7 @@ impl<'tcx> Clean for Ty<'tcx> { ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton) + ty::Bound(..) => panic!("Bound"), ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"), ty::GeneratorWitness(..) => panic!("GeneratorWitness"), ty::Infer(..) => panic!("Infer"), From d0447550dabc1b5fee1bde2a2663ebe15d6bbf2a Mon Sep 17 00:00:00 2001 From: scalexm Date: Mon, 22 Oct 2018 22:38:51 +0200 Subject: [PATCH 02/11] Shift both late bound regions and bound types --- src/librustc/infer/outlives/obligations.rs | 2 +- src/librustc/infer/sub.rs | 4 +- src/librustc/traits/fulfill.rs | 2 +- src/librustc/traits/project.rs | 4 +- src/librustc/traits/query/normalize.rs | 4 +- src/librustc/traits/select.rs | 16 +-- src/librustc/ty/flags.rs | 7 +- src/librustc/ty/fold.rs | 134 ++++++++++++------ src/librustc/ty/instance.rs | 2 +- src/librustc/ty/outlives.rs | 2 +- src/librustc/ty/sty.rs | 11 +- src/librustc/ty/subst.rs | 26 ++-- src/librustc/ty/util.rs | 4 +- src/librustc/ty/wf.rs | 14 +- src/librustc_codegen_llvm/callee.rs | 2 +- src/librustc_codegen_llvm/type_of.rs | 2 +- src/librustc_driver/test.rs | 12 +- .../borrow_check/nll/type_check/mod.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 6 +- .../implied_outlives_bounds.rs | 2 +- src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/mod.rs | 12 +- src/librustc_typeck/coherence/builtin.rs | 6 +- 25 files changed, 164 insertions(+), 118 deletions(-) diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index 5db850f1588b6..523f03c2cfc47 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -305,7 +305,7 @@ where ty, region, origin ); - assert!(!ty.has_escaping_regions()); + assert!(!ty.has_escaping_bound_vars()); let components = self.tcx.outlives_components(ty); self.components_must_outlive(origin, components, region); diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index 048810c042722..3b0f9a5e545fd 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -84,8 +84,8 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> // Shouldn't have any LBR here, so we can safely put // this under a binder below without fear of accidental // capture. - assert!(!a.has_escaping_regions()); - assert!(!b.has_escaping_regions()); + assert!(!a.has_escaping_bound_vars()); + assert!(!b.has_escaping_bound_vars()); // can't make progress on `A <: B` if both A and B are // type variables, so record an obligation. We also diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index cfa77b210e857..afe23e47bbf54 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -143,7 +143,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { debug!("normalize_projection_type(projection_ty={:?})", projection_ty); - debug_assert!(!projection_ty.has_escaping_regions()); + debug_assert!(!projection_ty.has_escaping_bound_vars()); // FIXME(#20304) -- cache diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 4eda47d31ebb5..c0bc214fe7a59 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -366,7 +366,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, let ty = ty.super_fold_with(self); match ty.sty { - ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => { // (*) + ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*) // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal { Reveal::UserFacing => ty, @@ -393,7 +393,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, } } - ty::Projection(ref data) if !data.has_escaping_regions() => { // (*) + ty::Projection(ref data) if !data.has_escaping_bound_vars() => { // (*) // (*) This is kind of hacky -- we need to be able to // handle normalization within binders because diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 4adb65dc58d91..59b086e35de31 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -100,7 +100,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { let ty = ty.super_fold_with(self); match ty.sty { - ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => { + ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*) // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal { @@ -138,7 +138,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx } } - ty::Projection(ref data) if !data.has_escaping_regions() => { + ty::Projection(ref data) if !data.has_escaping_bound_vars() => { // (*) // (*) This is kind of hacky -- we need to be able to // handle normalization within binders because diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 691c9d9da49bc..6670b83bdf87a 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -587,7 +587,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation: &TraitObligation<'tcx>, ) -> SelectionResult<'tcx, Selection<'tcx>> { debug!("select({:?})", obligation); - debug_assert!(!obligation.predicate.has_escaping_regions()); + debug_assert!(!obligation.predicate.has_escaping_bound_vars()); let stack = self.push_stack(TraitObligationStackList::empty(), obligation); @@ -690,7 +690,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match obligation.predicate { ty::Predicate::Trait(ref t) => { - debug_assert!(!t.has_escaping_regions()); + debug_assert!(!t.has_escaping_bound_vars()); let obligation = obligation.with(t.clone()); self.evaluate_trait_predicate_recursively(previous_stack, obligation) } @@ -722,9 +722,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { }, ty::Predicate::TypeOutlives(ref binder) => { - assert!(!binder.has_escaping_regions()); - // Check if the type has higher-ranked regions. - if binder.skip_binder().0.has_escaping_regions() { + assert!(!binder.has_escaping_bound_vars()); + // Check if the type has higher-ranked vars. + if binder.skip_binder().0.has_escaping_bound_vars() { // If so, this obligation is an error (for now). Eventually we should be // able to support additional cases here, like `for<'a> &'a str: 'a`. @@ -740,7 +740,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Ok(EvaluatedToErr) } } else { - // If the type has no late bound regions, then if we assign all + // If the type has no late bound vars, then if we assign all // the inference variables in it to be 'static, then the type // will be 'static itself. // @@ -1199,7 +1199,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { "candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})", cache_fresh_trait_pred, stack ); - debug_assert!(!stack.obligation.predicate.has_escaping_regions()); + debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars()); if let Some(c) = self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred) @@ -1801,7 +1801,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { placeholder_map: &infer::PlaceholderMap<'tcx>, snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, ) -> bool { - debug_assert!(!skol_trait_ref.has_escaping_regions()); + debug_assert!(!skol_trait_ref.has_escaping_bound_vars()); if self.infcx .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(skol_trait_ref), trait_bound) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 92e08878708f6..d0ea7f653d1e1 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -115,7 +115,10 @@ impl FlagComputation { self.add_substs(&substs.substs); } - &ty::Bound(_) => self.add_flags(TypeFlags::HAS_CANONICAL_VARS), + &ty::Bound(bound_ty) => { + self.add_flags(TypeFlags::HAS_CANONICAL_VARS); + self.add_binder(bound_ty.level); + } &ty::Infer(infer) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right? @@ -142,7 +145,7 @@ impl FlagComputation { &ty::Projection(ref data) => { // currently we can't normalize projections that // include bound regions, so track those separately. - if !data.has_escaping_regions() { + if !data.has_escaping_bound_vars() { self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION); } self.add_flags(TypeFlags::HAS_PROJECTION); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 80dfd263af9af..cb94d7d1083e8 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -67,18 +67,18 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { /// bound by `binder` or bound by some binder outside of `binder`. /// If `binder` is `ty::INNERMOST`, this indicates whether /// there are any late-bound regions that appear free. - fn has_regions_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { - self.visit_with(&mut HasEscapingRegionsVisitor { outer_index: binder }) + fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { + self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }) } /// True if this `self` has any regions that escape `binder` (and /// hence are not bound by it). - fn has_regions_bound_above(&self, binder: ty::DebruijnIndex) -> bool { - self.has_regions_bound_at_or_above(binder.shifted_in(1)) + fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool { + self.has_vars_bound_at_or_above(binder.shifted_in(1)) } - fn has_escaping_regions(&self) -> bool { - self.has_regions_bound_at_or_above(ty::INNERMOST) + fn has_escaping_bound_vars(&self) -> bool { + self.has_vars_bound_at_or_above(ty::INNERMOST) } fn has_type_flags(&self, flags: TypeFlags) -> bool { @@ -574,7 +574,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.has_regions_bound_at_or_above(self.current_index) { + if !t.has_vars_bound_at_or_above(self.current_index) { return t; } @@ -603,34 +603,79 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> { } /////////////////////////////////////////////////////////////////////////// -// Region shifter +// Shifter // -// Shifts the De Bruijn indices on all escaping bound regions by a +// Shifts the De Bruijn indices on all escaping bound vars by a // fixed amount. Useful in substitution or when otherwise introducing // a binding level that is not intended to capture the existing bound -// regions. See comment on `shift_regions_through_binders` method in +// vars. See comment on `shift_vars_through_binders` method in // `subst.rs` for more details. -pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind { - match region { - ty::ReLateBound(debruijn, br) => { - ty::ReLateBound(debruijn.shifted_in(amount), br) +struct Shifter<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, + + current_index: ty::DebruijnIndex, + amount: u32, +} + +impl Shifter<'a, 'gcx, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, amount: u32) -> Self { + Shifter { + tcx, + current_index: ty::INNERMOST, + amount, } - _ => { - region + } +} + +impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } + + fn fold_binder>(&mut self, t: &ty::Binder) -> ty::Binder { + self.current_index.shift_in(1); + let t = t.super_fold_with(self); + self.current_index.shift_out(1); + t + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + match *r { + ty::ReLateBound(debruijn, br) => { + if self.amount == 0 || debruijn < self.current_index { + r + } else { + let shifted = ty::ReLateBound(debruijn.shifted_in(self.amount), br); + self.tcx.mk_region(shifted) + } + } + _ => r + } + } + + fn fold_ty(&mut self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> { + match ty.sty { + ty::Bound(bound_ty) => { + if self.amount == 0 || bound_ty.level < self.current_index { + ty + } else { + let shifted = ty::BoundTy { + level: bound_ty.level.shifted_in(self.amount), + var: bound_ty.var, + kind: bound_ty.kind, + }; + self.tcx.mk_ty(ty::Bound(shifted)) + } + } + + _ => ty.super_fold_with(self), } } } -pub fn shift_region_ref<'a, 'gcx, 'tcx>( - tcx: TyCtxt<'a, 'gcx, 'tcx>, - region: ty::Region<'tcx>, - amount: u32) - -> ty::Region<'tcx> -{ +pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind { match region { - &ty::ReLateBound(debruijn, br) if amount > 0 => { - tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br)) + ty::ReLateBound(debruijn, br) => { + ty::ReLateBound(debruijn.shifted_in(amount), br) } _ => { region @@ -638,20 +683,19 @@ pub fn shift_region_ref<'a, 'gcx, 'tcx>( } } -pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - amount: u32, - value: &T) -> T - where T: TypeFoldable<'tcx> -{ - debug!("shift_regions(value={:?}, amount={})", +pub fn shift_vars<'a, 'gcx, 'tcx, T>( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + amount: u32, + value: &T +) -> T where T: TypeFoldable<'tcx> { + debug!("shift_vars(value={:?}, amount={})", value, amount); - value.fold_with(&mut RegionFolder::new(tcx, &mut false, &mut |region, _current_depth| { - shift_region_ref(tcx, region, amount) - })) + value.fold_with(&mut Shifter::new(tcx, amount)) } -/// An "escaping region" is a bound region whose binder is not part of `t`. +/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a +/// bound region or a bound type. /// /// So, for example, consider a type like the following, which has two binders: /// @@ -663,24 +707,24 @@ pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>, /// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner /// fn type*, that type has an escaping region: `'a`. /// -/// Note that what I'm calling an "escaping region" is often just called a "free region". However, -/// we already use the term "free region". It refers to the regions that we use to represent bound -/// regions on a fn definition while we are typechecking its body. +/// Note that what I'm calling an "escaping var" is often just called a "free var". However, +/// we already use the term "free var". It refers to the regions or types that we use to represent +/// bound regions or type params on a fn definition while we are typechecking its body. /// /// To clarify, conceptually there is no particular difference between -/// an "escaping" region and a "free" region. However, there is a big +/// an "escaping" var and a "free" var. However, there is a big /// difference in practice. Basically, when "entering" a binding /// level, one is generally required to do some sort of processing to -/// a bound region, such as replacing it with a fresh/placeholder -/// region, or making an entry in the environment to represent the -/// scope to which it is attached, etc. An escaping region represents -/// a bound region for which this processing has not yet been done. -struct HasEscapingRegionsVisitor { +/// a bound var, such as replacing it with a fresh/placeholder +/// var, or making an entry in the environment to represent the +/// scope to which it is attached, etc. An escaping var represents +/// a bound var for which this processing has not yet been done. +struct HasEscapingVarsVisitor { /// Anything bound by `outer_index` or "above" is escaping outer_index: ty::DebruijnIndex, } -impl<'tcx> TypeVisitor<'tcx> for HasEscapingRegionsVisitor { +impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { fn visit_binder>(&mut self, t: &Binder) -> bool { self.outer_index.shift_in(1); let result = t.super_visit_with(self); @@ -693,7 +737,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingRegionsVisitor { // `outer_index`, that means that `t` contains some content // bound at `outer_index` or above (because // `outer_exclusive_binder` is always 1 higher than the - // content in `t`). Therefore, `t` has some escaping regions. + // content in `t`). Therefore, `t` has some escaping vars. t.outer_exclusive_binder > self.outer_index } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 041565c8b5a07..2fc8ef548fa04 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -213,7 +213,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> { impl<'a, 'b, 'tcx> Instance<'tcx> { pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> Instance<'tcx> { - assert!(!substs.has_escaping_regions(), + assert!(!substs.has_escaping_bound_vars(), "substs of instance {:?} not normalized for codegen: {:?}", def_id, substs); Instance { def: InstanceDef::Item(def_id), substs: substs } diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index 4c820447be234..449730c9d0601 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -106,7 +106,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // we simply fallback to the most restrictive rule, which // requires that `Pi: 'a` for all `i`. ty::Projection(ref data) => { - if !data.has_escaping_regions() { + if !data.has_escaping_bound_vars() { // best case: no escaping regions, so push the // projection and skip the subtree (thus generating no // constraints for Pi). This defers the choice between diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 25f7496e8931c..e812486d1f89e 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -730,8 +730,8 @@ impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> { /// or some placeholder type. pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> { - // otherwise the escaping regions would be captured by the binder - // debug_assert!(!self_ty.has_escaping_regions()); + // otherwise the escaping vars would be captured by the binder + // debug_assert!(!self_ty.has_escaping_bound_vars()); ty::TraitRef { def_id: self.def_id, @@ -776,7 +776,7 @@ impl Binder { pub fn dummy<'tcx>(value: T) -> Binder where T: TypeFoldable<'tcx> { - debug_assert!(!value.has_escaping_regions()); + debug_assert!(!value.has_escaping_bound_vars()); Binder(value) } @@ -835,7 +835,7 @@ impl Binder { pub fn no_late_bound_regions<'tcx>(self) -> Option where T : TypeFoldable<'tcx> { - if self.skip_binder().has_escaping_regions() { + if self.skip_binder().has_escaping_bound_vars() { None } else { Some(self.skip_binder().clone()) @@ -1246,7 +1246,6 @@ impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) }); impl BoundTy { pub fn new(level: DebruijnIndex, var: BoundTyIndex) -> Self { - debug_assert_eq!(ty::INNERMOST, level); BoundTy { level, var, @@ -1283,7 +1282,7 @@ impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> { -> ty::ProjectionPredicate<'tcx> { // otherwise the escaping regions would be captured by the binders - debug_assert!(!self_ty.has_escaping_regions()); + debug_assert!(!self_ty.has_escaping_bound_vars()); ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 87c2c9b6005aa..9e85cfe7a12e7 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -355,7 +355,7 @@ impl<'tcx, T:TypeFoldable<'tcx>> Subst<'tcx> for T { span, root_ty: None, ty_stack_depth: 0, - region_binders_passed: 0 }; + binders_passed: 0 }; (*self).fold_with(&mut folder) } } @@ -377,16 +377,16 @@ struct SubstFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { ty_stack_depth: usize, // Number of region binders we have passed through while doing the substitution - region_binders_passed: u32, + binders_passed: u32, } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } fn fold_binder>(&mut self, t: &ty::Binder) -> ty::Binder { - self.region_binders_passed += 1; + self.binders_passed += 1; let t = t.super_fold_with(self); - self.region_binders_passed -= 1; + self.binders_passed -= 1; t } @@ -471,7 +471,7 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { } }; - self.shift_regions_through_binders(ty) + self.shift_vars_through_binders(ty) } /// It is sometimes necessary to adjust the debruijn indices during substitution. This occurs @@ -516,25 +516,25 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { /// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the /// first case we do not increase the Debruijn index and in the second case we do. The reason /// is that only in the second case have we passed through a fn binder. - fn shift_regions_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> { - debug!("shift_regions(ty={:?}, region_binders_passed={:?}, has_escaping_regions={:?})", - ty, self.region_binders_passed, ty.has_escaping_regions()); + fn shift_vars_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> { + debug!("shift_vars(ty={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})", + ty, self.binders_passed, ty.has_escaping_bound_vars()); - if self.region_binders_passed == 0 || !ty.has_escaping_regions() { + if self.binders_passed == 0 || !ty.has_escaping_bound_vars() { return ty; } - let result = ty::fold::shift_regions(self.tcx(), self.region_binders_passed, &ty); - debug!("shift_regions: shifted result = {:?}", result); + let result = ty::fold::shift_vars(self.tcx(), self.binders_passed, &ty); + debug!("shift_vars: shifted result = {:?}", result); result } fn shift_region_through_binders(&self, region: ty::Region<'tcx>) -> ty::Region<'tcx> { - if self.region_binders_passed == 0 || !region.has_escaping_regions() { + if self.binders_passed == 0 || !region.has_escaping_bound_vars() { return region; } - self.tcx().mk_region(ty::fold::shift_region(*region, self.region_binders_passed)) + self.tcx().mk_region(ty::fold::shift_region(*region, self.binders_passed)) } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 0a758285a29b1..1b1bbfd4deb8b 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -363,7 +363,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { erased_self_ty, predicates); - assert!(!erased_self_ty.has_escaping_regions()); + assert!(!erased_self_ty.has_escaping_bound_vars()); traits::elaborate_predicates(self, predicates) .filter_map(|predicate| { @@ -389,7 +389,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // 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_regions() { + if t == &erased_self_ty && !r.has_escaping_bound_vars() { Some(*r) } else { None diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index eb97f1177af1b..1336eac63f880 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -158,7 +158,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let infcx = &mut self.infcx; let param_env = self.param_env; self.out.iter() - .inspect(|pred| assert!(!pred.has_escaping_regions())) + .inspect(|pred| assert!(!pred.has_escaping_bound_vars())) .flat_map(|pred| { let mut selcx = traits::SelectionContext::new(infcx); let pred = traits::normalize(&mut selcx, param_env, cause.clone(), pred); @@ -190,7 +190,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { self.out.extend( trait_ref.substs.types() - .filter(|ty| !ty.has_escaping_regions()) + .filter(|ty| !ty.has_escaping_bound_vars()) .map(|ty| traits::Obligation::new(cause.clone(), param_env, ty::Predicate::WellFormed(ty)))); @@ -205,7 +205,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let trait_ref = data.trait_ref(self.infcx.tcx); self.compute_trait_ref(&trait_ref, Elaborate::None); - if !data.has_escaping_regions() { + if !data.has_escaping_bound_vars() { let predicate = trait_ref.to_predicate(); let cause = self.cause(traits::ProjectionWf(data)); self.out.push(traits::Obligation::new(cause, self.param_env, predicate)); @@ -229,7 +229,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { } fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) { - if !subty.has_escaping_regions() { + if !subty.has_escaping_bound_vars() { let cause = self.cause(cause); let trait_ref = ty::TraitRef { def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), @@ -300,7 +300,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { ty::Ref(r, rty, _) => { // WfReference - if !r.has_escaping_regions() && !rty.has_escaping_regions() { + if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() { let cause = self.cause(traits::ReferenceOutlivesReferent(ty)); self.out.push( traits::Obligation::new( @@ -451,7 +451,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { .map(|pred| traits::Obligation::new(cause.clone(), self.param_env, pred)) - .filter(|pred| !pred.has_escaping_regions()) + .filter(|pred| !pred.has_escaping_bound_vars()) .collect() } @@ -490,7 +490,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // Note: in fact we only permit builtin traits, not `Bar<'d>`, I // am looking forward to the future here. - if !data.has_escaping_regions() { + if !data.has_escaping_bound_vars() { let implicit_bounds = object_region_bounds(self.infcx.tcx, data); diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 7300bac96182b..c8c693257d52f 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -44,7 +44,7 @@ pub fn get_fn( debug!("get_fn(instance={:?})", instance); assert!(!instance.substs.needs_infer()); - assert!(!instance.substs.has_escaping_regions()); + assert!(!instance.substs.has_escaping_bound_vars()); assert!(!instance.substs.has_param_types()); let sig = instance.fn_sig(cx.tcx); diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 03ded64e64235..b01d7e3a776f7 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -285,7 +285,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { debug!("llvm_type({:#?})", self); - assert!(!self.ty.has_escaping_regions(), "{:?} has escaping regions", self.ty); + assert!(!self.ty.has_escaping_bound_vars(), "{:?} has escaping bound vars", self.ty); // Make sure lifetimes are erased, to avoid generating distinct LLVM // types for Rust types that only differ in the choice of lifetimes. diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index f18f40bf7a144..28b7c610a91c0 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -616,22 +616,22 @@ fn escaping() { // Theta = [A -> &'a foo] env.create_simple_region_hierarchy(); - assert!(!env.t_nil().has_escaping_regions()); + assert!(!env.t_nil().has_escaping_bound_vars()); let t_rptr_free1 = env.t_rptr_free(1); - assert!(!t_rptr_free1.has_escaping_regions()); + assert!(!t_rptr_free1.has_escaping_bound_vars()); let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, d1()); - assert!(t_rptr_bound1.has_escaping_regions()); + assert!(t_rptr_bound1.has_escaping_bound_vars()); let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2()); - assert!(t_rptr_bound2.has_escaping_regions()); + assert!(t_rptr_bound2.has_escaping_bound_vars()); // t_fn = fn(A) let t_param = env.t_param(0); - assert!(!t_param.has_escaping_regions()); + assert!(!t_param.has_escaping_bound_vars()); let t_fn = env.t_fn(&[t_param], env.t_nil()); - assert!(!t_fn.has_escaping_regions()); + assert!(!t_fn.has_escaping_bound_vars()); }) } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index aa9564bdcaf03..91c2035838d08 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -359,7 +359,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { } fn sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> { - if ty.has_escaping_regions() || ty.references_error() { + if ty.has_escaping_bound_vars() || ty.references_error() { span_mirbug_and_err!(self, parent, "bad type {:?}", ty) } else { ty diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 8c6966691328a..6b39060d6fc23 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -905,12 +905,12 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_ty: Ty<'tcx>, impl_ty: Ty<'tcx>, output: &mut Vec>) { - assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_regions() && - !impl_ty.needs_subst() && !impl_ty.has_escaping_regions()); + assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_bound_vars() && + !impl_ty.needs_subst() && !impl_ty.has_escaping_bound_vars()); if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty { let poly_trait_ref = trait_ty.principal().with_self_ty(tcx, impl_ty); - assert!(!poly_trait_ref.has_escaping_regions()); + assert!(!poly_trait_ref.has_escaping_bound_vars()); // Walk all methods of the trait, including those of its supertraits let methods = tcx.vtable_methods(poly_trait_ref); diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index cde08f6832ace..b97450f966221 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -108,7 +108,7 @@ fn compute_implied_outlives_bounds<'tcx>( // From the full set of obligations, just filter down to the // region relationships. implied_bounds.extend(obligations.into_iter().flat_map(|obligation| { - assert!(!obligation.has_escaping_regions()); + assert!(!obligation.has_escaping_bound_vars()); match obligation.predicate { ty::Predicate::Trait(..) | ty::Predicate::Subtype(..) | diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index fb7c237a536bd..010561d1001e5 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -460,7 +460,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Create a `PolyFnSig`. Note the oddity that late bound // regions appearing free in `expected_sig` are now bound up // in this binder we are creating. - assert!(!expected_sig.sig.has_regions_bound_above(ty::INNERMOST)); + assert!(!expected_sig.sig.has_vars_bound_above(ty::INNERMOST)); let bound_sig = ty::Binder::bind(self.tcx.mk_fn_sig( expected_sig.sig.inputs().iter().cloned(), expected_sig.sig.output(), diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 04c32fa88271a..11448750618e2 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -331,7 +331,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { value } }; - assert!(!bounds.has_escaping_regions()); + assert!(!bounds.has_escaping_bound_vars()); let cause = traits::ObligationCause::misc(span, self.body_id); obligations.extend(traits::predicates_for_generics(cause.clone(), diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 5a8a9632350f2..305efd0d75af6 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1374,7 +1374,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn_sig, substs); - assert!(!substs.has_escaping_regions()); + assert!(!substs.has_escaping_bound_vars()); // It is possible for type parameters or early-bound lifetimes // to appear in the signature of `self`. The substitutions we diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9ac733b159ba6..791b5a0bdd92a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -653,8 +653,8 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) { debug!("register_predicate({:?})", obligation); - if obligation.has_escaping_regions() { - span_bug!(obligation.cause.span, "escaping regions in predicate {:?}", + if obligation.has_escaping_bound_vars() { + span_bug!(obligation.cause.span, "escaping bound vars in predicate {:?}", obligation); } self.fulfillment_cx @@ -1928,7 +1928,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { } fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { - if ty.has_escaping_regions() { + if ty.has_escaping_bound_vars() { ty // FIXME: normalization and escaping regions } else { self.normalize_associated_types_in(span, &ty) @@ -2431,7 +2431,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { cause: traits::ObligationCause<'tcx>, predicates: &ty::InstantiatedPredicates<'tcx>) { - assert!(!predicates.has_escaping_regions()); + assert!(!predicates.has_escaping_bound_vars()); debug!("add_obligations_for_parameters(predicates={:?})", predicates); @@ -5188,8 +5188,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }, ); - assert!(!substs.has_escaping_regions()); - assert!(!ty.has_escaping_regions()); + assert!(!substs.has_escaping_bound_vars()); + assert!(!ty.has_escaping_bound_vars()); // Write the "user substs" down first thing for later. let hir_id = self.tcx.hir.node_to_hir_id(node_id); diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 99c6ba457faa0..a5ad31e0b6b5f 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -99,7 +99,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: let span = tcx.hir.span(impl_node_id); let param_env = tcx.param_env(impl_did); - assert!(!self_type.has_escaping_regions()); + assert!(!self_type.has_escaping_bound_vars()); debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type); @@ -176,7 +176,7 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>( let span = tcx.hir.span(impl_node_id); let source = tcx.type_of(impl_did); - assert!(!source.has_escaping_regions()); + assert!(!source.has_escaping_bound_vars()); let target = { let trait_ref = tcx.impl_trait_ref(impl_did).unwrap(); assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait); @@ -356,7 +356,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, let span = gcx.hir.span(impl_node_id); let param_env = gcx.param_env(impl_did); - assert!(!source.has_escaping_regions()); + assert!(!source.has_escaping_bound_vars()); let err_info = CoerceUnsizedInfo { custom_kind: None }; From 3dd303aa894e65219117b831f5c6284ec1077eae Mon Sep 17 00:00:00 2001 From: scalexm Date: Tue, 23 Oct 2018 13:42:23 +0200 Subject: [PATCH 03/11] Rename `BoundTyIndex` to `BoundVar` --- src/librustc/ich/impls_ty.rs | 2 +- src/librustc/infer/canonical/canonicalizer.rs | 14 +++++++------- src/librustc/infer/canonical/mod.rs | 10 +++++----- src/librustc/infer/canonical/query_response.rs | 14 +++++++------- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/sty.rs | 8 ++++---- src/librustc/ty/subst.rs | 4 ++-- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 5873dd2eab7d6..c950942ee345d 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -147,7 +147,7 @@ impl<'a> HashStable> for ty::RegionVid { } } -impl<'gcx> HashStable> for ty::BoundTyIndex { +impl<'gcx> HashStable> for ty::BoundVar { #[inline] fn hash_stable(&self, hcx: &mut StableHashingContext<'gcx>, diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index a7634b8bd2a7a..5a9887e4af436 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -23,7 +23,7 @@ use infer::InferCtxt; use std::sync::atomic::Ordering; use ty::fold::{TypeFoldable, TypeFolder}; use ty::subst::Kind; -use ty::{self, BoundTy, BoundTyIndex, Lift, List, Ty, TyCtxt, TypeFlags}; +use ty::{self, BoundTy, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; @@ -277,7 +277,7 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> { query_state: &'cx mut OriginalQueryValues<'tcx>, // Note that indices is only used once `var_values` is big enough to be // heap-allocated. - indices: FxHashMap, BoundTyIndex>, + indices: FxHashMap, BoundVar>, canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode, needs_canonical_flags: TypeFlags, } @@ -455,7 +455,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { /// or returns an existing variable if `kind` has already been /// seen. `kind` is expected to be an unbound variable (or /// potentially a free region). - fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTyIndex { + fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundVar { let Canonicalizer { variables, query_state, @@ -475,7 +475,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { // direct linear search of `var_values`. if let Some(idx) = var_values.iter().position(|&k| k == kind) { // `kind` is already present in `var_values`. - BoundTyIndex::new(idx) + BoundVar::new(idx) } else { // `kind` isn't present in `var_values`. Append it. Likewise // for `info` and `variables`. @@ -490,11 +490,11 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { *indices = var_values .iter() .enumerate() - .map(|(i, &kind)| (kind, BoundTyIndex::new(i))) + .map(|(i, &kind)| (kind, BoundVar::new(i))) .collect(); } // The cv is the index of the appended element. - BoundTyIndex::new(var_values.len() - 1) + BoundVar::new(var_values.len() - 1) } } else { // `var_values` is large. Do a hashmap search via `indices`. @@ -502,7 +502,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { variables.push(info); var_values.push(kind); assert_eq!(variables.len(), var_values.len()); - BoundTyIndex::new(variables.len() - 1) + BoundVar::new(variables.len() - 1) }) }; diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index f2b7c6e0d0d98..b6f7941472522 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -40,7 +40,7 @@ use std::ops::Index; use syntax::source_map::Span; use ty::fold::TypeFoldable; use ty::subst::Kind; -use ty::{self, BoundTyIndex, Lift, List, Region, TyCtxt}; +use ty::{self, BoundVar, Lift, List, Region, TyCtxt}; mod canonicalizer; @@ -73,7 +73,7 @@ impl<'gcx> UseSpecializedDecodable for CanonicalVarInfos<'gcx> {} /// canonicalized query response. #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)] pub struct CanonicalVarValues<'tcx> { - pub var_values: IndexVec>, + pub var_values: IndexVec>, } /// When we canonicalize a value to form a query, we wind up replacing @@ -337,7 +337,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { variables: &List, universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex, ) -> CanonicalVarValues<'tcx> { - let var_values: IndexVec> = variables + let var_values: IndexVec> = variables .iter() .map(|info| self.instantiate_canonical_var(span, *info, &universe_map)) .collect(); @@ -456,10 +456,10 @@ BraceStructLiftImpl! { } where R: Lift<'tcx> } -impl<'tcx> Index for CanonicalVarValues<'tcx> { +impl<'tcx> Index for CanonicalVarValues<'tcx> { type Output = Kind<'tcx>; - fn index(&self, value: BoundTyIndex) -> &Kind<'tcx> { + fn index(&self, value: BoundVar) -> &Kind<'tcx> { &self.var_values[value] } } diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 27ee33a452ef8..6e17eabdbb714 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -35,7 +35,7 @@ use traits::{FulfillmentContext, TraitEngine}; use traits::{Obligation, ObligationCause, PredicateObligation}; use ty::fold::TypeFoldable; use ty::subst::{Kind, UnpackedKind}; -use ty::{self, BoundTyIndex, Lift, Ty, TyCtxt}; +use ty::{self, BoundVar, Lift, Ty, TyCtxt}; impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> { /// The "main method" for a canonicalized trait query. Given the @@ -273,7 +273,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { for (index, original_value) in original_values.var_values.iter().enumerate() { // ...with the value `v_r` of that variable from the query. let result_value = query_response.substitute_projected(self.tcx, &result_subst, |v| { - &v.var_values[BoundTyIndex::new(index)] + &v.var_values[BoundVar::new(index)] }); match (original_value.unpack(), result_value.unpack()) { (UnpackedKind::Lifetime(ty::ReErased), UnpackedKind::Lifetime(ty::ReErased)) => { @@ -423,7 +423,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { // is directly equal to one of the canonical variables in the // result, then we can type the corresponding value from the // input. See the example above. - let mut opt_values: IndexVec>> = + let mut opt_values: IndexVec>> = IndexVec::from_elem_n(None, query_response.variables.len()); // In terms of our example above, we are iterating over pairs like: @@ -457,7 +457,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { .enumerate() .map(|(index, info)| { if info.is_existential() { - match opt_values[BoundTyIndex::new(index)] { + match opt_values[BoundVar::new(index)] { Some(k) => k, None => self.instantiate_canonical_var(cause.span, *info, |u| { universe_map[u.as_usize()] @@ -496,7 +496,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { // canonical variable; this is taken from // `query_response.var_values` after applying the substitution // `result_subst`. - let substituted_query_response = |index: BoundTyIndex| -> Kind<'tcx> { + let substituted_query_response = |index: BoundVar| -> Kind<'tcx> { query_response.substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index]) }; @@ -552,12 +552,12 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { cause: &ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, variables1: &OriginalQueryValues<'tcx>, - variables2: impl Fn(BoundTyIndex) -> Kind<'tcx>, + variables2: impl Fn(BoundVar) -> Kind<'tcx>, ) -> InferResult<'tcx, ()> { self.commit_if_ok(|_| { let mut obligations = vec![]; for (index, value1) in variables1.var_values.iter().enumerate() { - let value2 = variables2(BoundTyIndex::new(index)); + let value2 = variables2(BoundVar::new(index)); match (value1.unpack(), value2.unpack()) { (UnpackedKind::Type(v1), UnpackedKind::Type(v2)) => { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 6ce65177442dc..d2ef5d0b66a77 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -63,7 +63,7 @@ use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, use hir; -pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundTyIndex, DebruijnIndex, INNERMOST}; +pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundVar, DebruijnIndex, INNERMOST}; pub use self::sty::{FnSig, GenSig, CanonicalPolyFnSig, PolyFnSig, PolyGenSig}; pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut}; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e812486d1f89e..1890006b51417 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1171,7 +1171,7 @@ pub enum RegionKind { ReClosureBound(RegionVid), /// Canonicalized region, used only when preparing a trait query. - ReCanonical(BoundTyIndex), + ReCanonical(BoundVar), } impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {} @@ -1225,13 +1225,13 @@ pub enum InferTy { } newtype_index! { - pub struct BoundTyIndex { .. } + pub struct BoundVar { .. } } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct BoundTy { pub level: DebruijnIndex, - pub var: BoundTyIndex, + pub var: BoundVar, pub kind: BoundTyKind, } @@ -1245,7 +1245,7 @@ impl_stable_hash_for!(struct BoundTy { level, var, kind }); impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) }); impl BoundTy { - pub fn new(level: DebruijnIndex, var: BoundTyIndex) -> Self { + pub fn new(level: DebruijnIndex, var: BoundVar) -> Self { BoundTy { level, var, diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 9e85cfe7a12e7..fd26b263efb0f 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -12,7 +12,7 @@ use hir::def_id::DefId; use infer::canonical::Canonical; -use ty::{self, BoundTyIndex, Lift, List, Ty, TyCtxt}; +use ty::{self, BoundVar, Lift, List, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use serialize::{self, Encodable, Encoder, Decodable, Decoder}; @@ -553,7 +553,7 @@ impl CanonicalUserSubsts<'tcx> { return false; } - self.value.substs.iter().zip(BoundTyIndex::new(0)..).all(|(kind, cvar)| { + self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { match kind.unpack() { UnpackedKind::Type(ty) => match ty.sty { ty::Bound(ref b) => cvar == b.var, From ee569c796d093adfdf632e99978b6e8877716e68 Mon Sep 17 00:00:00 2001 From: scalexm Date: Tue, 23 Oct 2018 16:28:53 +0200 Subject: [PATCH 04/11] Rename `BoundTy` field `level` -> `index` --- src/librustc/ty/flags.rs | 2 +- src/librustc/ty/fold.rs | 4 ++-- src/librustc/ty/sty.rs | 8 ++++---- src/librustc/util/ppaux.rs | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index d0ea7f653d1e1..6c1070f74e0d5 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -117,7 +117,7 @@ impl FlagComputation { &ty::Bound(bound_ty) => { self.add_flags(TypeFlags::HAS_CANONICAL_VARS); - self.add_binder(bound_ty.level); + self.add_binder(bound_ty.index); } &ty::Infer(infer) => { diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index cb94d7d1083e8..87ff5d2a36d89 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -655,11 +655,11 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> { fn fold_ty(&mut self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> { match ty.sty { ty::Bound(bound_ty) => { - if self.amount == 0 || bound_ty.level < self.current_index { + if self.amount == 0 || bound_ty.index < self.current_index { ty } else { let shifted = ty::BoundTy { - level: bound_ty.level.shifted_in(self.amount), + index: bound_ty.index.shifted_in(self.amount), var: bound_ty.var, kind: bound_ty.kind, }; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 1890006b51417..9c20d9a238e93 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1230,7 +1230,7 @@ newtype_index! { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct BoundTy { - pub level: DebruijnIndex, + pub index: DebruijnIndex, pub var: BoundVar, pub kind: BoundTyKind, } @@ -1241,13 +1241,13 @@ pub enum BoundTyKind { Param(InternedString), } -impl_stable_hash_for!(struct BoundTy { level, var, kind }); +impl_stable_hash_for!(struct BoundTy { index, var, kind }); impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) }); impl BoundTy { - pub fn new(level: DebruijnIndex, var: BoundVar) -> Self { + pub fn new(index: DebruijnIndex, var: BoundVar) -> Self { BoundTy { - level, + index, var, kind: BoundTyKind::Anon, } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 320fee5638e2d..222bbc67b0d52 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1120,10 +1120,10 @@ define_print! { Bound(bound_ty) => { match bound_ty.kind { ty::BoundTyKind::Anon => { - if bound_ty.level == ty::INNERMOST { + if bound_ty.index == ty::INNERMOST { write!(f, "?{}", bound_ty.var.index()) } else { - write!(f, "?{}_{}", bound_ty.level.index(), bound_ty.var.index()) + write!(f, "?{}_{}", bound_ty.index.index(), bound_ty.var.index()) } } From 1f8de94f3bb1ab148f717507ec1baf78c6a7d207 Mon Sep 17 00:00:00 2001 From: scalexm Date: Tue, 23 Oct 2018 19:47:53 +0200 Subject: [PATCH 05/11] Adjust bound tys indices in canonicalization --- src/librustc/infer/canonical/canonicalizer.rs | 31 +++++++++++++++---- .../infer/canonical/query_response.rs | 1 + src/librustc/infer/canonical/substitute.rs | 30 +++++++++++++++--- src/librustc/ty/subst.rs | 5 ++- 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 5a9887e4af436..a54d977a5172c 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -280,6 +280,8 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> { indices: FxHashMap, BoundVar>, canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode, needs_canonical_flags: TypeFlags, + + binder_index: ty::DebruijnIndex, } impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> { @@ -287,11 +289,23 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> self.tcx } + fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder + where T: TypeFoldable<'tcx> + { + self.binder_index.shift_in(1); + let t = t.super_fold_with(self); + self.binder_index.shift_out(1); + t + } + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(..) => { - // leave bound regions alone - r + ty::ReLateBound(index, ..) => { + if index >= self.binder_index { + bug!("escaping late bound region during canonicalization") + } else { + r + } } ty::ReVar(vid) => { @@ -337,8 +351,12 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> bug!("encountered a fresh type during canonicalization") } - ty::Bound(_) => { - bug!("encountered a bound type during canonicalization") + ty::Bound(bound_ty) => { + if bound_ty.index >= self.binder_index { + bug!("escaping bound type during canonicalization") + } else { + t + } } ty::Closure(..) @@ -422,6 +440,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { variables: SmallVec::new(), query_state, indices: FxHashMap::default(), + binder_index: ty::INNERMOST, }; let out_value = value.fold_with(&mut canonicalizer); @@ -567,7 +586,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { kind: CanonicalVarKind::Ty(ty_kind), }; let var = self.canonical_var(info, ty_var.into()); - self.tcx().mk_ty(ty::Bound(BoundTy::new(ty::INNERMOST, var))) + self.tcx().mk_ty(ty::Bound(BoundTy::new(self.binder_index, var))) } } } diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 6e17eabdbb714..06e97a71ce5ce 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -433,6 +433,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { UnpackedKind::Type(result_value) => { // e.g., here `result_value` might be `?0` in the example above... if let ty::Bound(b) = result_value.sty { + assert_eq!(b.index, ty::INNERMOST); // in which case we would set `canonical_vars[0]` to `Some(?U)`. opt_values[b.var] = Some(*original_value); } diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs index 80a2497bbf613..5b2e758d81673 100644 --- a/src/librustc/infer/canonical/substitute.rs +++ b/src/librustc/infer/canonical/substitute.rs @@ -69,13 +69,18 @@ where } else if !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) { value.clone() } else { - value.fold_with(&mut CanonicalVarValuesSubst { tcx, var_values }) + value.fold_with(&mut CanonicalVarValuesSubst { + tcx, + var_values, + binder_index: ty::INNERMOST, + }) } } struct CanonicalVarValuesSubst<'cx, 'gcx: 'tcx, 'tcx: 'cx> { tcx: TyCtxt<'cx, 'gcx, 'tcx>, var_values: &'cx CanonicalVarValues<'tcx>, + binder_index: ty::DebruijnIndex, } impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'gcx, 'tcx> { @@ -83,12 +88,29 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g self.tcx } + fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder + where T: TypeFoldable<'tcx> + { + self.binder_index.shift_in(1); + let t = t.super_fold_with(self); + self.binder_index.shift_out(1); + t + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match t.sty { ty::Bound(b) => { - match self.var_values.var_values[b.var].unpack() { - UnpackedKind::Type(ty) => ty, - r => bug!("{:?} is a type but value is {:?}", b, r), + if b.index == self.binder_index { + match self.var_values.var_values[b.var].unpack() { + UnpackedKind::Type(ty) => ty::fold::shift_vars( + self.tcx, + self.binder_index.index() as u32, + &ty + ), + r => bug!("{:?} is a type but value is {:?}", b, r), + } + } else { + t } } _ => { diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index fd26b263efb0f..6bdbeb8f604fc 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -556,7 +556,10 @@ impl CanonicalUserSubsts<'tcx> { self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { match kind.unpack() { UnpackedKind::Type(ty) => match ty.sty { - ty::Bound(ref b) => cvar == b.var, + ty::Bound(ref b) => { + assert_eq!(b.index, ty::INNERMOST); + cvar == b.var + } _ => false, }, From 45be1ac0fcb7ac2d4d8e52c6543e8384e7c1a6ea Mon Sep 17 00:00:00 2001 From: scalexm Date: Wed, 24 Oct 2018 10:29:42 +0200 Subject: [PATCH 06/11] Remove `ReCanonical` in favor of `ReLateBound` --- src/librustc/ich/impls_ty.rs | 3 -- src/librustc/infer/canonical/canonicalizer.rs | 16 +++---- src/librustc/infer/canonical/mod.rs | 2 +- .../infer/canonical/query_response.rs | 48 +++++++++++-------- src/librustc/infer/canonical/substitute.rs | 31 ++++++++---- src/librustc/infer/combine.rs | 1 - src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/infer/freshen.rs | 1 - .../infer/lexical_region_resolve/mod.rs | 4 +- src/librustc/infer/region_constraints/mod.rs | 4 -- src/librustc/ty/flags.rs | 2 - src/librustc/ty/fold.rs | 14 ++++-- src/librustc/ty/mod.rs | 7 +-- src/librustc/ty/sty.rs | 30 ++++++------ src/librustc/ty/subst.rs | 17 ++++--- src/librustc/util/ppaux.rs | 7 --- src/librustc_borrowck/borrowck/check_loans.rs | 1 - .../borrowck/gather_loans/mod.rs | 1 - .../error_reporting/region_name.rs | 3 +- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/outlives/utils.rs | 1 - src/librustc_typeck/variance/constraints.rs | 1 - src/librustdoc/clean/mod.rs | 1 - 23 files changed, 98 insertions(+), 101 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index c950942ee345d..a93e31480f3bb 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -100,9 +100,6 @@ for ty::RegionKind { ty::ReEmpty => { // No variant fields to hash for these ... } - ty::ReCanonical(c) => { - c.hash_stable(hcx, hasher); - } ty::ReLateBound(db, ty::BrAnon(i)) => { db.hash_stable(hcx, hasher); i.hash_stable(hcx, hasher); diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index a54d977a5172c..9c70606349b5d 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -331,8 +331,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> | ty::ReErased => self.canonicalize_region_mode .canonicalize_free_region(self, r), - ty::ReClosureBound(..) | ty::ReCanonical(_) => { - bug!("canonical region encountered during canonicalization") + ty::ReClosureBound(..) => { + bug!("closure bound region encountered during canonicalization") } } } @@ -407,12 +407,6 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { where V: TypeFoldable<'tcx> + Lift<'gcx>, { - debug_assert!( - !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS), - "canonicalizing a canonical value: {:?}", - value, - ); - let needs_canonical_flags = if canonicalize_region_mode.any() { TypeFlags::HAS_FREE_REGIONS | TypeFlags::KEEP_IN_LOCAL_TCX } else { @@ -569,7 +563,11 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { let var = self.canonical_var(info, r.into()); - self.tcx().mk_region(ty::ReCanonical(var)) + let region = ty::ReLateBound( + self.binder_index, + ty::BoundRegion::BrAnon(var.index() as u32) + ); + self.tcx().mk_region(region) } /// Given a type variable `ty_var` of the given kind, first check diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index b6f7941472522..f7eb7118f412f 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -20,7 +20,7 @@ //! - a map M (of type `CanonicalVarValues`) from those canonical //! variables back to the original. //! -//! We can then do queries using T2. These will give back constriants +//! We can then do queries using T2. These will give back constraints //! on the canonical variables which can be translated, using the map //! M, into constraints in our source context. This process of //! translating the results back is done by the diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 06e97a71ce5ce..4858d1d09192a 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -308,11 +308,12 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { // ...also include the other query region constraints from the query. output_query_region_constraints.extend( query_response.value.region_constraints.iter().filter_map(|r_c| { - let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below - let k1 = substitute_value(self.tcx, &result_subst, &k1); - let r2 = substitute_value(self.tcx, &result_subst, &r2); - if k1 != r2.into() { - Some(ty::Binder::bind(ty::OutlivesPredicate(k1, r2))) + let ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below + let k1 = substitute_value(self.tcx, &result_subst, &ty::Binder::bind(*k1)); + let r2 = substitute_value(self.tcx, &result_subst, &ty::Binder::bind(*r2)); + if k1 != r2.map_bound(|bound| bound.into()) { + let predicate = ty::OutlivesPredicate(*k1.skip_binder(), *r2.skip_binder()); + Some(ty::Binder::bind(predicate)) } else { None } @@ -433,16 +434,21 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { UnpackedKind::Type(result_value) => { // e.g., here `result_value` might be `?0` in the example above... if let ty::Bound(b) = result_value.sty { + // ...in which case we would set `canonical_vars[0]` to `Some(?U)`. + + // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(b.index, ty::INNERMOST); - // in which case we would set `canonical_vars[0]` to `Some(?U)`. opt_values[b.var] = Some(*original_value); } } UnpackedKind::Lifetime(result_value) => { // e.g., here `result_value` might be `'?1` in the example above... - if let &ty::RegionKind::ReCanonical(index) = result_value { - // in which case we would set `canonical_vars[0]` to `Some('static)`. - opt_values[index] = Some(*original_value); + if let &ty::RegionKind::ReLateBound(index, br) = result_value { + // ... in which case we would set `canonical_vars[0]` to `Some('static)`. + + // We only allow a `ty::INNERMOST` index in substitutions. + assert_eq!(index, ty::INNERMOST); + opt_values[br.as_bound_var()] = Some(*original_value); } } } @@ -525,21 +531,23 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { .iter() .map(move |constraint| { let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below - let k1 = substitute_value(self.tcx, result_subst, k1); - let r2 = substitute_value(self.tcx, result_subst, r2); + let k1 = substitute_value(self.tcx, result_subst, &ty::Binder::bind(*k1)); + let r2 = substitute_value(self.tcx, result_subst, &ty::Binder::bind(*r2)); Obligation::new( cause.clone(), param_env, - match k1.unpack() { + match k1.skip_binder().unpack() { UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives( - ty::Binder::dummy( - ty::OutlivesPredicate(r1, r2) - )), + ty::Binder::bind( + ty::OutlivesPredicate(r1, r2.skip_binder()) + ) + ), UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives( - ty::Binder::dummy(ty::OutlivesPredicate( - t1, r2 - ))) + ty::Binder::bind( + ty::OutlivesPredicate(t1, r2.skip_binder()) + ) + ), } ) }) @@ -621,11 +629,11 @@ pub fn make_query_outlives<'tcx>( } Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1), }) - .map(ty::Binder::dummy) // no bound regions in the code above + .map(ty::Binder::dummy) // no bound vars in the code above .chain( outlives_obligations .map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r)) - .map(ty::Binder::dummy), // no bound regions in the code above + .map(ty::Binder::dummy) // no bound vars in the code above ) .collect(); diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs index 5b2e758d81673..7839c8922660a 100644 --- a/src/librustc/infer/canonical/substitute.rs +++ b/src/librustc/infer/canonical/substitute.rs @@ -19,7 +19,7 @@ use infer::canonical::{Canonical, CanonicalVarValues}; use ty::fold::{TypeFoldable, TypeFolder}; use ty::subst::UnpackedKind; -use ty::{self, Ty, TyCtxt, TypeFlags}; +use ty::{self, Ty, TyCtxt}; impl<'tcx, V> Canonical<'tcx, V> { /// Instantiate the wrapped value, replacing each canonical value @@ -64,9 +64,9 @@ where T: TypeFoldable<'tcx>, { if var_values.var_values.is_empty() { - debug_assert!(!value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS)); value.clone() - } else if !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) { + } else if !value.has_escaping_bound_vars() { + // There are no bound vars to substitute. value.clone() } else { value.fold_with(&mut CanonicalVarValuesSubst { @@ -104,8 +104,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g match self.var_values.var_values[b.var].unpack() { UnpackedKind::Type(ty) => ty::fold::shift_vars( self.tcx, - self.binder_index.index() as u32, - &ty + &ty, + self.binder_index.index() as u32 ), r => bug!("{:?} is a type but value is {:?}", b, r), } @@ -114,7 +114,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g } } _ => { - if !t.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) { + if !t.has_vars_bound_at_or_above(self.binder_index) { + // Nothing more to substitute. t } else { t.super_fold_with(self) @@ -125,10 +126,20 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match r { - ty::RegionKind::ReCanonical(c) => match self.var_values.var_values[*c].unpack() { - UnpackedKind::Lifetime(l) => l, - r => bug!("{:?} is a region but value is {:?}", c, r), - }, + ty::RegionKind::ReLateBound(index, br) => { + if *index == self.binder_index { + match self.var_values.var_values[br.as_bound_var()].unpack() { + UnpackedKind::Lifetime(l) => ty::fold::shift_region( + self.tcx, + l, + self.binder_index.index() as u32, + ), + r => bug!("{:?} is a region but value is {:?}", br, r), + } + } else { + r + } + } _ => r.super_fold_with(self), } } diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 0ee03bc4c6e00..f13210926a79b 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -485,7 +485,6 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' } } - ty::ReCanonical(..) | ty::ReClosureBound(..) => { span_bug!( self.span, diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index d19c495af3b96..1963d366e7a66 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -152,7 +152,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } // We shouldn't encounter an error message with ReClosureBound. - ty::ReCanonical(..) | ty::ReClosureBound(..) => { + ty::ReClosureBound(..) => { bug!("encountered unexpected ReClosureBound: {:?}", region,); } }; diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index c12e64b4c2c59..b53444992fa21 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -114,7 +114,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { self.tcx().types.re_erased } - ty::ReCanonical(..) | ty::ReClosureBound(..) => { bug!( "encountered unexpected region: {:?}", diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index 8f28e9a320df2..75f503d3bcfb4 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -260,9 +260,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> { let tcx = self.tcx(); match (a, b) { - (&ty::ReCanonical(..), _) - | (_, &ty::ReCanonical(..)) - | (&ty::ReClosureBound(..), _) + (&ty::ReClosureBound(..), _) | (_, &ty::ReClosureBound(..)) | (&ReLateBound(..), _) | (_, &ReLateBound(..)) diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index c82603bf56057..46b12d01829e7 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -833,10 +833,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> { ty::RePlaceholder(placeholder) => placeholder.universe, ty::ReClosureBound(vid) | ty::ReVar(vid) => self.var_universe(vid), ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region), - ty::ReCanonical(..) => bug!( - "region_universe(): encountered canonical region {:?}", - region - ), } } diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 6c1070f74e0d5..0764f363250dd 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -116,7 +116,6 @@ impl FlagComputation { } &ty::Bound(bound_ty) => { - self.add_flags(TypeFlags::HAS_CANONICAL_VARS); self.add_binder(bound_ty.index); } @@ -127,7 +126,6 @@ impl FlagComputation { ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { - self.add_flags(TypeFlags::HAS_CANONICAL_VARS); } ty::TyVar(_) | diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 87ff5d2a36d89..31542582f9499 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -672,10 +672,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> { } } -pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind { +pub fn shift_region<'a, 'gcx, 'tcx>( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + region: ty::Region<'tcx>, + amount: u32 +) -> ty::Region<'tcx> { match region { - ty::ReLateBound(debruijn, br) => { - ty::ReLateBound(debruijn.shifted_in(amount), br) + ty::ReLateBound(debruijn, br) if amount > 0 => { + tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), *br)) } _ => { region @@ -685,8 +689,8 @@ pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind { pub fn shift_vars<'a, 'gcx, 'tcx, T>( tcx: TyCtxt<'a, 'gcx, 'tcx>, - amount: u32, - value: &T + value: &T, + amount: u32 ) -> T where T: TypeFoldable<'tcx> { debug!("shift_vars(value={:?}, amount={})", value, amount); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d2ef5d0b66a77..7d693cd5523df 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -463,13 +463,9 @@ bitflags! { // Currently we can't normalize projections w/ bound regions. const HAS_NORMALIZABLE_PROJECTION = 1 << 12; - // Set if this includes a "canonical" type or region var -- - // ought to be true only for the results of canonicalization. - const HAS_CANONICAL_VARS = 1 << 13; - /// Does this have any `ReLateBound` regions? Used to check /// if a global bound is safe to evaluate. - const HAS_RE_LATE_BOUND = 1 << 14; + const HAS_RE_LATE_BOUND = 1 << 13; const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | TypeFlags::HAS_SELF.bits | @@ -490,7 +486,6 @@ bitflags! { TypeFlags::HAS_TY_CLOSURE.bits | TypeFlags::HAS_FREE_LOCAL_NAMES.bits | TypeFlags::KEEP_IN_LOCAL_TCX.bits | - TypeFlags::HAS_CANONICAL_VARS.bits | TypeFlags::HAS_RE_LATE_BOUND.bits; } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 9c20d9a238e93..f23bd01765aa5 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -77,6 +77,17 @@ impl BoundRegion { _ => false, } } + + /// When canonicalizing, we replace unbound inference variables and free + /// regions with anonymous late bound regions. This method asserts that + /// we have an anonymous late bound region, which hence may refer to + /// a canonical variable. + pub fn as_bound_var(&self) -> BoundVar { + match *self { + BoundRegion::BrAnon(var) => BoundVar::from_u32(var), + _ => bug!("bound region is not anonymous"), + } + } } /// N.B., If you change this, you'll probably want to change the corresponding @@ -758,11 +769,11 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { } } -/// Binder is a binder for higher-ranked lifetimes. It is part of the +/// Binder is a binder for higher-ranked lifetimes or types. It is part of the /// compiler's representation for things like `for<'a> Fn(&'a isize)` /// (which would be represented by the type `PolyTraitRef == /// Binder`). Note that when we instantiate, -/// erase, or otherwise "discharge" these bound regions, we change the +/// erase, or otherwise "discharge" these bound vars, we change the /// type from `Binder` to just `T` (see /// e.g. `liberate_late_bound_regions`). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] @@ -770,7 +781,7 @@ pub struct Binder(T); impl Binder { /// Wraps `value` in a binder, asserting that `value` does not - /// contain any bound regions that would be bound by the + /// contain any bound vars that would be bound by the /// binder. This is commonly used to 'inject' a value T into a /// different binding level. pub fn dummy<'tcx>(value: T) -> Binder @@ -780,9 +791,8 @@ impl Binder { Binder(value) } - /// Wraps `value` in a binder, binding late-bound regions (if any). - pub fn bind<'tcx>(value: T) -> Binder - { + /// Wraps `value` in a binder, binding higher-ranked vars (if any). + pub fn bind<'tcx>(value: T) -> Binder { Binder(value) } @@ -1169,9 +1179,6 @@ pub enum RegionKind { /// `ClosureRegionRequirements` that are produced by MIR borrowck. /// See `ClosureRegionRequirements` for more details. ReClosureBound(RegionVid), - - /// Canonicalized region, used only when preparing a trait query. - ReCanonical(BoundVar), } impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {} @@ -1381,7 +1388,6 @@ impl RegionKind { RegionKind::ReEmpty => false, RegionKind::ReErased => false, RegionKind::ReClosureBound(..) => false, - RegionKind::ReCanonical(..) => false, } } @@ -1468,10 +1474,6 @@ impl RegionKind { } ty::ReErased => { } - ty::ReCanonical(..) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_CANONICAL_VARS; - } ty::ReClosureBound(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 6bdbeb8f604fc..498d704eb9e28 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -475,8 +475,8 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { } /// It is sometimes necessary to adjust the debruijn indices during substitution. This occurs - /// when we are substituting a type with escaping regions into a context where we have passed - /// through region binders. That's quite a mouthful. Let's see an example: + /// when we are substituting a type with escaping bound vars into a context where we have + /// passed through binders. That's quite a mouthful. Let's see an example: /// /// ``` /// type Func = fn(A); @@ -524,7 +524,7 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { return ty; } - let result = ty::fold::shift_vars(self.tcx(), self.binders_passed, &ty); + let result = ty::fold::shift_vars(self.tcx(), &ty, self.binders_passed); debug!("shift_vars: shifted result = {:?}", result); result @@ -534,7 +534,7 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { if self.binders_passed == 0 || !region.has_escaping_bound_vars() { return region; } - self.tcx().mk_region(ty::fold::shift_region(*region, self.binders_passed)) + ty::fold::shift_region(self.tcx, region, self.binders_passed) } } @@ -556,7 +556,8 @@ impl CanonicalUserSubsts<'tcx> { self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { match kind.unpack() { UnpackedKind::Type(ty) => match ty.sty { - ty::Bound(ref b) => { + ty::Bound(b) => { + // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(b.index, ty::INNERMOST); cvar == b.var } @@ -564,7 +565,11 @@ impl CanonicalUserSubsts<'tcx> { }, UnpackedKind::Lifetime(r) => match r { - ty::ReCanonical(cvar1) => cvar == *cvar1, + ty::ReLateBound(index, br) => { + // We only allow a `ty::INNERMOST` index in substitutions. + assert_eq!(*index, ty::INNERMOST); + cvar == br.as_bound_var() + } _ => false, }, } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 222bbc67b0d52..5ec4f55b142eb 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -790,9 +790,6 @@ define_print! { ty::ReEarlyBound(ref data) => { write!(f, "{}", data.name) } - ty::ReCanonical(_) => { - write!(f, "'_") - } ty::ReLateBound(_, br) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { @@ -860,10 +857,6 @@ define_print! { write!(f, "{:?}", vid) } - ty::ReCanonical(c) => { - write!(f, "'?{}", c.index()) - } - ty::RePlaceholder(placeholder) => { write!(f, "RePlaceholder({:?})", placeholder) } diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 1fc9ee07a1ae4..a802729e3fbdb 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -426,7 +426,6 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { // These cannot exist in borrowck RegionKind::ReVar(..) | - RegionKind::ReCanonical(..) | RegionKind::RePlaceholder(..) | RegionKind::ReClosureBound(..) | RegionKind::ReErased => span_bug!(borrow_span, diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 1f83c30a3876a..78a31ed668fca 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -363,7 +363,6 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { ty::ReStatic => self.item_ub, - ty::ReCanonical(_) | ty::ReEmpty | ty::ReClosureBound(..) | ty::ReLateBound(..) | diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 2b671891fca6d..99372a511a9de 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -277,8 +277,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { | ty::RePlaceholder(..) | ty::ReEmpty | ty::ReErased - | ty::ReClosureBound(..) - | ty::ReCanonical(..) => None, + | ty::ReClosureBound(..) => None, } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index afd8c251b7650..46f2c0c76a0c7 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1748,7 +1748,7 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> { self.region_bounds.iter().map(|&(region_bound, span)| { // account for the binder being introduced below; no need to shift `param_ty` // because, at present at least, it can only refer to early-bound regions - let region_bound = tcx.mk_region(ty::fold::shift_region(*region_bound, 1)); + let region_bound = ty::fold::shift_region(tcx, region_bound, 1); let outlives = ty::OutlivesPredicate(param_ty, region_bound); (ty::Binder::dummy(outlives).to_predicate(), span) }).chain( diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs index 96b75c4792d75..d748d93d8988e 100644 --- a/src/librustc_typeck/outlives/utils.rs +++ b/src/librustc_typeck/outlives/utils.rs @@ -167,7 +167,6 @@ fn is_free_region<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, region: Region<'_>) -> bool RegionKind::ReEmpty | RegionKind::ReErased | RegionKind::ReClosureBound(..) - | RegionKind::ReCanonical(..) | RegionKind::ReScope(..) | RegionKind::ReVar(..) | RegionKind::RePlaceholder(..) diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index b11b034ee13cc..47d34c909961e 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -427,7 +427,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // way early-bound regions do, so we skip them here. } - ty::ReCanonical(_) | ty::ReFree(..) | ty::ReClosureBound(..) | ty::ReScope(..) | diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8391db9a37d50..e71b3ccb01dbe 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1260,7 +1260,6 @@ impl Clean> for ty::RegionKind { ty::RePlaceholder(..) | ty::ReEmpty | ty::ReClosureBound(_) | - ty::ReCanonical(_) | ty::ReErased => None } } From d99195ad8fefb5752423c0c5224a2395e7e9255b Mon Sep 17 00:00:00 2001 From: scalexm Date: Wed, 24 Oct 2018 22:30:34 +0200 Subject: [PATCH 07/11] Rename `Binder::no_late_bound_regions` to `Binder::no_bound_vars` --- src/librustc/infer/outlives/verify.rs | 2 +- src/librustc/traits/auto_trait.rs | 4 ++-- src/librustc/traits/fulfill.rs | 8 ++++---- src/librustc/traits/mod.rs | 2 +- src/librustc/traits/project.rs | 2 +- src/librustc/traits/query/outlives_bounds.rs | 2 +- src/librustc/traits/select.rs | 4 ++-- src/librustc/ty/sty.rs | 14 +++++++------- src/librustc_codegen_llvm/base.rs | 2 +- .../nll/type_check/constraint_conversion.rs | 4 ++-- .../borrow_check/nll/type_check/mod.rs | 4 ++-- src/librustc_mir/monomorphize/collector.rs | 2 +- src/librustc_mir/shim.rs | 4 +++- src/librustc_mir/transform/lower_128bit.rs | 2 +- src/librustc_traits/implied_outlives_bounds.rs | 4 ++-- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/intrinsic.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- 18 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs index e1db295b7e14d..88d45671b9afd 100644 --- a/src/librustc/infer/outlives/verify.rs +++ b/src/librustc/infer/outlives/verify.rs @@ -323,7 +323,7 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> { predicates .into_iter() .filter_map(|p| p.as_ref().to_opt_type_outlives()) - .filter_map(|p| p.no_late_bound_regions()) + .filter_map(|p| p.no_bound_vars()) .filter(move |p| compare_ty(p.0)) } } diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index 50ca6ca78ab3a..e87e425762d56 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -683,8 +683,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } &ty::Predicate::TypeOutlives(ref binder) => { match ( - binder.no_late_bound_regions(), - binder.map_bound_ref(|pred| pred.0).no_late_bound_regions(), + binder.no_bound_vars(), + binder.map_bound_ref(|pred| pred.0).no_bound_vars(), ) { (None, Some(t_a)) => { select.infcx().register_region_obligation_with_cause( diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index afe23e47bbf54..aea956461f27b 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -349,15 +349,15 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, } ty::Predicate::TypeOutlives(ref binder) => { - // Check if there are higher-ranked regions. - match binder.no_late_bound_regions() { + // Check if there are higher-ranked vars. + match binder.no_bound_vars() { // If there are, inspect the underlying type further. None => { // Convert from `Binder>` to `Binder`. let binder = binder.map_bound_ref(|pred| pred.0); - // Check if the type has any bound regions. - match binder.no_late_bound_regions() { + // Check if the type has any bound vars. + match binder.no_bound_vars() { // If so, this obligation is an error (for now). Eventually we should be // able to support additional cases here, like `for<'a> &'a str: 'a`. // NOTE: this is duplicate-implemented between here and fulfillment. diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 6b2ec64668e9b..5e2f1fe08b90e 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -352,7 +352,7 @@ impl<'tcx> GoalKind<'tcx> { domain_goal: PolyDomainGoal<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>, ) -> GoalKind<'tcx> { - match domain_goal.no_late_bound_regions() { + match domain_goal.no_bound_vars() { Some(p) => p.into_goal(), None => GoalKind::Quantified( QuantifierKind::Universal, diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index c0bc214fe7a59..80358294d056c 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1619,7 +1619,7 @@ impl<'cx, 'gcx, 'tcx> ProjectionCacheKey<'tcx> { let infcx = selcx.infcx(); // We don't do cross-snapshot caching of obligations with escaping regions, // so there's no cache key to use - predicate.no_late_bound_regions() + predicate.no_bound_vars() .map(|predicate| ProjectionCacheKey { // We don't attempt to match up with a specific type-variable state // from a specific call to `opt_normalize_projection_type` - if diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc/traits/query/outlives_bounds.rs index 99f557d44d9aa..b3fae3bab3471 100644 --- a/src/librustc/traits/query/outlives_bounds.rs +++ b/src/librustc/traits/query/outlives_bounds.rs @@ -164,7 +164,7 @@ pub fn explicit_outlives_bounds<'tcx>( ty::Predicate::ClosureKind(..) | ty::Predicate::TypeOutlives(..) | ty::Predicate::ConstEvaluatable(..) => None, - ty::Predicate::RegionOutlives(ref data) => data.no_late_bound_regions().map( + ty::Predicate::RegionOutlives(ref data) => data.no_bound_vars().map( |ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a), ), }) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 6670b83bdf87a..45dad508af560 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2168,7 +2168,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // T: Trait // so it seems ok if we (conservatively) fail to accept that `Unsize` // obligation above. Should be possible to extend this in the future. - let source = match obligation.self_ty().no_late_bound_regions() { + let source = match obligation.self_ty().no_bound_vars() { Some(t) => t, None => { // Don't add any candidates if there are bound regions. @@ -3235,7 +3235,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // assemble_candidates_for_unsizing should ensure there are no late bound // regions here. See the comment there for more details. let source = self.infcx - .shallow_resolve(obligation.self_ty().no_late_bound_regions().unwrap()); + .shallow_resolve(obligation.self_ty().no_bound_vars().unwrap()); let target = obligation .predicate .skip_binder() diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index f23bd01765aa5..fbc77fdfea30d 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -799,10 +799,10 @@ impl Binder { /// Skips the binder and returns the "bound" value. This is a /// risky thing to do because it's easy to get confused about /// debruijn indices and the like. It is usually better to - /// discharge the binder using `no_late_bound_regions` or + /// discharge the binder using `no_bound_vars` or /// `replace_late_bound_regions` or something like /// that. `skip_binder` is only valid when you are either - /// extracting data that has nothing to do with bound regions, you + /// extracting data that has nothing to do with bound vars, you /// are doing some sort of test that does not involve bound /// regions, or you are being very careful about your depth /// accounting. @@ -811,7 +811,7 @@ impl Binder { /// /// - extracting the def-id from a PolyTraitRef; /// - comparing the self type of a PolyTraitRef to see if it is equal to - /// a type parameter `X`, since the type `X` does not reference any regions + /// a type parameter `X`, since the type `X` does not reference any regions pub fn skip_binder(&self) -> &T { &self.0 } @@ -833,17 +833,17 @@ impl Binder { } /// Unwraps and returns the value within, but only if it contains - /// no bound regions at all. (In other words, if this binder -- + /// no bound vars at all. (In other words, if this binder -- /// and indeed any enclosing binder -- doesn't bind anything at /// all.) Otherwise, returns `None`. /// /// (One could imagine having a method that just unwraps a single - /// binder, but permits late-bound regions bound by enclosing + /// binder, but permits late-bound vars bound by enclosing /// binders, but that would require adjusting the debruijn /// indices, and given the shallow binding structure we often use, /// would not be that useful.) - pub fn no_late_bound_regions<'tcx>(self) -> Option - where T : TypeFoldable<'tcx> + pub fn no_bound_vars<'tcx>(self) -> Option + where T: TypeFoldable<'tcx> { if self.skip_binder().has_escaping_bound_vars() { None diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index a4c7a7123b964..c1f096bc1911f 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -557,7 +557,7 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) { // regions must appear in the argument // listing. let main_ret_ty = cx.tcx.erase_regions( - &main_ret_ty.no_late_bound_regions().unwrap(), + &main_ret_ty.no_bound_vars().unwrap(), ); if declare::get_defined_value(cx, "main").is_some() { diff --git a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs index 5904138ef603a..35ec478143546 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs @@ -82,9 +82,9 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> { // when we move to universes, we will, and this assertion // will start to fail. let ty::OutlivesPredicate(k1, r2) = - query_constraint.no_late_bound_regions().unwrap_or_else(|| { + query_constraint.no_bound_vars().unwrap_or_else(|| { bug!( - "query_constraint {:?} contained bound regions", + "query_constraint {:?} contained bound vars", query_constraint, ); }); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 91c2035838d08..734ddbc3ab9a7 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -2214,8 +2214,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { .enumerate() .filter_map(|(idx, constraint)| { let ty::OutlivesPredicate(k1, r2) = - constraint.no_late_bound_regions().unwrap_or_else(|| { - bug!("query_constraint {:?} contained bound regions", constraint,); + constraint.no_bound_vars().unwrap_or_else(|| { + bug!("query_constraint {:?} contained bound vars", constraint,); }); match k1.unpack() { diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 6b39060d6fc23..8e27635dee8c1 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1082,7 +1082,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> { // regions must appear in the argument // listing. let main_ret_ty = self.tcx.erase_regions( - &main_ret_ty.no_late_bound_regions().unwrap(), + &main_ret_ty.no_bound_vars().unwrap(), ); let start_instance = Instance::resolve( diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 7061504cd0ae7..76a8501fb177a 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -844,7 +844,9 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, let param_env = gcx.param_env(def_id); // Normalize the sig. - let sig = gcx.fn_sig(def_id).no_late_bound_regions().expect("LBR in ADT constructor signature"); + let sig = gcx.fn_sig(def_id) + .no_bound_vars() + .expect("LBR in ADT constructor signature"); let sig = gcx.normalize_erasing_regions(param_env, sig); let (adt_def, substs) = match sig.output().sty { diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs index bd7d9d367618b..80072153167f3 100644 --- a/src/librustc_mir/transform/lower_128bit.rs +++ b/src/librustc_mir/transform/lower_128bit.rs @@ -143,7 +143,7 @@ fn check_lang_item_type<'a, 'tcx, D>( { let did = tcx.require_lang_item(lang_item); let poly_sig = tcx.fn_sig(did); - let sig = poly_sig.no_late_bound_regions().unwrap(); + let sig = poly_sig.no_bound_vars().unwrap(); let lhs_ty = lhs.ty(local_decls, tcx); let rhs_ty = rhs.ty(local_decls, tcx); let place_ty = place.ty(local_decls, tcx).to_ty(tcx); diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index b97450f966221..7cc064f9c3d3d 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -122,14 +122,14 @@ fn compute_implied_outlives_bounds<'tcx>( vec![] } - ty::Predicate::RegionOutlives(ref data) => match data.no_late_bound_regions() { + ty::Predicate::RegionOutlives(ref data) => match data.no_bound_vars() { None => vec![], Some(ty::OutlivesPredicate(r_a, r_b)) => { vec![OutlivesBound::RegionSubRegion(r_b, r_a)] } }, - ty::Predicate::TypeOutlives(ref data) => match data.no_late_bound_regions() { + ty::Predicate::TypeOutlives(ref data) => match data.no_bound_vars() { None => vec![], Some(ty::OutlivesPredicate(ty_a, r_b)) => { let ty_a = infcx.resolve_type_vars_if_possible(&ty_a); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 3204ef556f5dd..40f2072079a5a 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -816,7 +816,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); } // Replace constructor type with constructed type for tuple struct patterns. let pat_ty = pat_ty.fn_sig(tcx).output(); - let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type"); + let pat_ty = pat_ty.no_bound_vars().expect("expected fn type"); self.demand_eqtype(pat.span, expected, pat_ty); diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index da96d4f0cba42..3156458b4aa4a 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -419,7 +419,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut structural_to_nomimal = FxHashMap::default(); let sig = tcx.fn_sig(def_id); - let sig = sig.no_late_bound_regions().unwrap(); + let sig = sig.no_bound_vars().unwrap(); if intr.inputs.len() != sig.inputs().len() { span_err!(tcx.sess, it.span, E0444, "platform-specific intrinsic has invalid number of \ diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index eb52a013b0566..bf3887ee8fcdd 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -208,7 +208,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { item_def_id: DefId, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx> { - if let Some(trait_ref) = poly_trait_ref.no_late_bound_regions() { + if let Some(trait_ref) = poly_trait_ref.no_bound_vars() { self.tcx().mk_projection(item_def_id, trait_ref.substs) } else { // no late-bound regions, we can just ignore the binder From 142359c2204f8be1d1efbf9ae8558bf7135a1618 Mon Sep 17 00:00:00 2001 From: scalexm Date: Wed, 24 Oct 2018 23:41:40 +0200 Subject: [PATCH 08/11] Extend `ty::fold::RegionReplacer` to `ty::fold::BoundVarReplacer` Use the new `BoundVarReplacer` to perform canonical substitutions. --- src/librustc/infer/canonical/substitute.rs | 89 ++------- src/librustc/ty/fold.rs | 200 ++++++++++++++------- 2 files changed, 149 insertions(+), 140 deletions(-) diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs index 7839c8922660a..3fd86f9c6a1d9 100644 --- a/src/librustc/infer/canonical/substitute.rs +++ b/src/librustc/infer/canonical/substitute.rs @@ -17,9 +17,9 @@ //! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html use infer::canonical::{Canonical, CanonicalVarValues}; -use ty::fold::{TypeFoldable, TypeFolder}; +use ty::fold::TypeFoldable; use ty::subst::UnpackedKind; -use ty::{self, Ty, TyCtxt}; +use ty::{self, TyCtxt}; impl<'tcx, V> Canonical<'tcx, V> { /// Instantiate the wrapped value, replacing each canonical value @@ -65,82 +65,21 @@ where { if var_values.var_values.is_empty() { value.clone() - } else if !value.has_escaping_bound_vars() { - // There are no bound vars to substitute. - value.clone() } else { - value.fold_with(&mut CanonicalVarValuesSubst { - tcx, - var_values, - binder_index: ty::INNERMOST, - }) - } -} - -struct CanonicalVarValuesSubst<'cx, 'gcx: 'tcx, 'tcx: 'cx> { - tcx: TyCtxt<'cx, 'gcx, 'tcx>, - var_values: &'cx CanonicalVarValues<'tcx>, - binder_index: ty::DebruijnIndex, -} - -impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'gcx, 'tcx> { - fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> { - self.tcx - } - - fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder - where T: TypeFoldable<'tcx> - { - self.binder_index.shift_in(1); - let t = t.super_fold_with(self); - self.binder_index.shift_out(1); - t - } - - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.sty { - ty::Bound(b) => { - if b.index == self.binder_index { - match self.var_values.var_values[b.var].unpack() { - UnpackedKind::Type(ty) => ty::fold::shift_vars( - self.tcx, - &ty, - self.binder_index.index() as u32 - ), - r => bug!("{:?} is a type but value is {:?}", b, r), - } - } else { - t - } + let fld_r = |br: ty::BoundRegion| { + match var_values.var_values[br.as_bound_var()].unpack() { + UnpackedKind::Lifetime(l) => l, + r => bug!("{:?} is a region but value is {:?}", br, r), } - _ => { - if !t.has_vars_bound_at_or_above(self.binder_index) { - // Nothing more to substitute. - t - } else { - t.super_fold_with(self) - } - } - } - } + }; - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match r { - ty::RegionKind::ReLateBound(index, br) => { - if *index == self.binder_index { - match self.var_values.var_values[br.as_bound_var()].unpack() { - UnpackedKind::Lifetime(l) => ty::fold::shift_region( - self.tcx, - l, - self.binder_index.index() as u32, - ), - r => bug!("{:?} is a region but value is {:?}", br, r), - } - } else { - r - } + let fld_t = |bound_ty: ty::BoundTy| { + match var_values.var_values[bound_ty.var].unpack() { + UnpackedKind::Type(ty) => ty, + r => bug!("{:?} is a type but value is {:?}", bound_ty, r), } - _ => r.super_fold_with(self), - } + }; + + tcx.replace_escaping_bound_vars(value, fld_r, fld_t) } } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 31542582f9499..06cc316f7883a 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -416,11 +416,10 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFolder<'a, 'gcx, 'tcx> { } /////////////////////////////////////////////////////////////////////////// -// Late-bound region replacer +// Bound vars replacer -// Replaces the escaping regions in a type. - -struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +/// Replaces the escaping bound vars (late bound regions or bound types) in a type. +struct BoundVarReplacer<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, /// As with `RegionFolder`, represents the index of a binder *just outside* @@ -428,7 +427,82 @@ struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { current_index: ty::DebruijnIndex, fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), - map: BTreeMap> + fld_t: &'a mut (dyn FnMut(ty::BoundTy) -> ty::Ty<'tcx> + 'a), +} + +impl<'a, 'gcx, 'tcx> BoundVarReplacer<'a, 'gcx, 'tcx> { + fn new( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + fld_r: &'a mut F, + fld_t: &'a mut G + ) -> Self + where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, + G: FnMut(ty::BoundTy) -> ty::Ty<'tcx> + { + BoundVarReplacer { + tcx, + current_index: ty::INNERMOST, + fld_r, + fld_t, + } + } +} + +impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } + + fn fold_binder>(&mut self, t: &ty::Binder) -> ty::Binder { + self.current_index.shift_in(1); + let t = t.super_fold_with(self); + self.current_index.shift_out(1); + t + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match t.sty { + ty::Bound(bound_ty) => { + if bound_ty.index == self.current_index { + let fld_t = &mut self.fld_t; + let ty = fld_t(bound_ty); + ty::fold::shift_vars( + self.tcx, + &ty, + self.current_index.as_u32() + ) + } else { + t + } + } + _ => { + if !t.has_vars_bound_at_or_above(self.current_index) { + // Nothing more to substitute. + t + } else { + t.super_fold_with(self) + } + } + } + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + match *r { + ty::ReLateBound(debruijn, br) if debruijn == self.current_index => { + let fld_r = &mut self.fld_r; + let region = fld_r(br); + if let ty::ReLateBound(debruijn1, br) = *region { + // If the callback returns a late-bound region, + // that region should always use the INNERMOST + // debruijn index. Then we adjust it to the + // correct depth. + assert_eq!(debruijn1, ty::INNERMOST); + self.tcx.mk_region(ty::ReLateBound(debruijn, br)) + } else { + region + } + } + _ => r + } + } } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { @@ -440,16 +514,65 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// same `BoundRegion` will reuse the previous result. A map is /// returned at the end with each bound region and the free region /// that replaced it. - pub fn replace_late_bound_regions(self, + /// + /// This method only replaces late bound regions and the result may still + /// contain escaping bound types. + pub fn replace_late_bound_regions( + self, value: &Binder, - mut f: F) - -> (T, BTreeMap>) - where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx>, - T : TypeFoldable<'tcx>, + mut fld_r: F + ) -> (T, BTreeMap>) + where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, + T: TypeFoldable<'tcx> { - let mut replacer = RegionReplacer::new(self, &mut f); + let mut map = BTreeMap::new(); + let mut real_fldr = |br| { + *map.entry(br).or_insert_with(|| fld_r(br)) + }; + + // identity for bound types + let mut fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty)); + + let mut replacer = BoundVarReplacer::new(self, &mut real_fldr, &mut fld_t); let result = value.skip_binder().fold_with(&mut replacer); - (result, replacer.map) + (result, map) + } + + /// Replace all escaping bound vars. The `fld_r` closure replaces escaping + /// bound regions while the `flr_t` closure replaces escaping bound types. + pub fn replace_escaping_bound_vars( + self, + value: &T, + mut fld_r: F, + mut fld_t: G + ) -> T + where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, + G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>, + T: TypeFoldable<'tcx> + { + if !value.has_escaping_bound_vars() { + value.clone() + } else { + let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t); + let result = value.fold_with(&mut replacer); + result + } + } + + /// Replace all types or regions bound by the given `Binder`. The `fld_r` + /// closure replaces bound regions while the `flr_t` closure replaces bound + /// types. + pub fn replace_bound_vars( + self, + value: &Binder, + fld_r: F, + fld_t: G + ) -> T + where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, + G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>, + T: TypeFoldable<'tcx> + { + self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t) } /// Replace any late-bound regions bound in `value` with @@ -549,59 +672,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> RegionReplacer<'a, 'gcx, 'tcx> { - fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, fld_r: &'a mut F) - -> RegionReplacer<'a, 'gcx, 'tcx> - where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx> - { - RegionReplacer { - tcx, - current_index: ty::INNERMOST, - fld_r, - map: BTreeMap::default() - } - } -} - -impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - - fn fold_binder>(&mut self, t: &ty::Binder) -> ty::Binder { - self.current_index.shift_in(1); - let t = t.super_fold_with(self); - self.current_index.shift_out(1); - t - } - - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.has_vars_bound_at_or_above(self.current_index) { - return t; - } - - t.super_fold_with(self) - } - - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { - ty::ReLateBound(debruijn, br) if debruijn == self.current_index => { - let fld_r = &mut self.fld_r; - let region = *self.map.entry(br).or_insert_with(|| fld_r(br)); - if let ty::ReLateBound(debruijn1, br) = *region { - // If the callback returns a late-bound region, - // that region should always use the INNERMOST - // debruijn index. Then we adjust it to the - // correct depth. - assert_eq!(debruijn1, ty::INNERMOST); - self.tcx.mk_region(ty::ReLateBound(debruijn, br)) - } else { - region - } - } - _ => r - } - } -} - /////////////////////////////////////////////////////////////////////////// // Shifter // From af8196b9d3b2e613c3a550a30445309d5feeb764 Mon Sep 17 00:00:00 2001 From: scalexm Date: Thu, 25 Oct 2018 14:13:24 +0200 Subject: [PATCH 09/11] Fix doc comment --- src/librustc/infer/canonical/canonicalizer.rs | 2 +- src/librustc/ty/fold.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 9c70606349b5d..61a861a8a1cd8 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -565,7 +565,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { let var = self.canonical_var(info, r.into()); let region = ty::ReLateBound( self.binder_index, - ty::BoundRegion::BrAnon(var.index() as u32) + ty::BoundRegion::BrAnon(var.as_u32()) ); self.tcx().mk_region(region) } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 06cc316f7883a..8c822adf7b023 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -539,7 +539,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } /// Replace all escaping bound vars. The `fld_r` closure replaces escaping - /// bound regions while the `flr_t` closure replaces escaping bound types. + /// bound regions while the `fld_t` closure replaces escaping bound types. pub fn replace_escaping_bound_vars( self, value: &T, @@ -560,7 +560,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } /// Replace all types or regions bound by the given `Binder`. The `fld_r` - /// closure replaces bound regions while the `flr_t` closure replaces bound + /// closure replaces bound regions while the `fld_t` closure replaces bound /// types. pub fn replace_bound_vars( self, From 07519975308af252a2fea6b89c3ad59374e29f39 Mon Sep 17 00:00:00 2001 From: scalexm Date: Thu, 25 Oct 2018 15:40:06 +0200 Subject: [PATCH 10/11] Rename `as_bound_var` to `assert_bound_var` --- src/librustc/infer/canonical/query_response.rs | 2 +- src/librustc/infer/canonical/substitute.rs | 2 +- src/librustc/ty/sty.rs | 2 +- src/librustc/ty/subst.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 4858d1d09192a..5154abd6ce544 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -448,7 +448,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(index, ty::INNERMOST); - opt_values[br.as_bound_var()] = Some(*original_value); + opt_values[br.assert_bound_var()] = Some(*original_value); } } } diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs index 3fd86f9c6a1d9..b8c1ed236c0ba 100644 --- a/src/librustc/infer/canonical/substitute.rs +++ b/src/librustc/infer/canonical/substitute.rs @@ -67,7 +67,7 @@ where value.clone() } else { let fld_r = |br: ty::BoundRegion| { - match var_values.var_values[br.as_bound_var()].unpack() { + match var_values.var_values[br.assert_bound_var()].unpack() { UnpackedKind::Lifetime(l) => l, r => bug!("{:?} is a region but value is {:?}", br, r), } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index fbc77fdfea30d..6929cb988d051 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -82,7 +82,7 @@ impl BoundRegion { /// regions with anonymous late bound regions. This method asserts that /// we have an anonymous late bound region, which hence may refer to /// a canonical variable. - pub fn as_bound_var(&self) -> BoundVar { + pub fn assert_bound_var(&self) -> BoundVar { match *self { BoundRegion::BrAnon(var) => BoundVar::from_u32(var), _ => bug!("bound region is not anonymous"), diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 498d704eb9e28..c1aed36c92ddf 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -568,7 +568,7 @@ impl CanonicalUserSubsts<'tcx> { ty::ReLateBound(index, br) => { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(*index, ty::INNERMOST); - cvar == br.as_bound_var() + cvar == br.assert_bound_var() } _ => false, }, From c5ed72fbfe8aae9ebc4c73dce3f1ef11388913d9 Mon Sep 17 00:00:00 2001 From: scalexm Date: Thu, 25 Oct 2018 16:01:10 +0200 Subject: [PATCH 11/11] Substitute binders directly --- .../infer/canonical/query_response.rs | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 5154abd6ce544..f4607f7a9092f 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -308,12 +308,14 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { // ...also include the other query region constraints from the query. output_query_region_constraints.extend( query_response.value.region_constraints.iter().filter_map(|r_c| { - let ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below - let k1 = substitute_value(self.tcx, &result_subst, &ty::Binder::bind(*k1)); - let r2 = substitute_value(self.tcx, &result_subst, &ty::Binder::bind(*r2)); - if k1 != r2.map_bound(|bound| bound.into()) { - let predicate = ty::OutlivesPredicate(*k1.skip_binder(), *r2.skip_binder()); - Some(ty::Binder::bind(predicate)) + let r_c = substitute_value(self.tcx, &result_subst, r_c); + + // Screen out `'a: 'a` cases -- we skip the binder here but + // only care the inner values to one another, so they are still at + // consistent binding levels. + let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); + if k1 != r2.into() { + Some(r_c) } else { None } @@ -530,22 +532,21 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { unsubstituted_region_constraints .iter() .map(move |constraint| { - let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below - let k1 = substitute_value(self.tcx, result_subst, &ty::Binder::bind(*k1)); - let r2 = substitute_value(self.tcx, result_subst, &ty::Binder::bind(*r2)); + let constraint = substitute_value(self.tcx, result_subst, constraint); + let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below Obligation::new( cause.clone(), param_env, - match k1.skip_binder().unpack() { + match k1.unpack() { UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives( ty::Binder::bind( - ty::OutlivesPredicate(r1, r2.skip_binder()) + ty::OutlivesPredicate(r1, r2) ) ), UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives( ty::Binder::bind( - ty::OutlivesPredicate(t1, r2.skip_binder()) + ty::OutlivesPredicate(t1, r2) ) ), }