use self::TyKind::*;
use crate::infer::canonical::Canonical;
+use crate::ty::fold::BoundVarsCollector;
+use crate::ty::fold::ValidateBoundVars;
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
use crate::ty::InferTy::{self, *};
use crate::ty::{
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)]
#[derive(HashStable)]
pub struct BoundRegion {
+ pub var: BoundVar,
pub kind: BoundRegionKind,
}
-impl BoundRegion {
- /// 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 assert_bound_var(&self) -> BoundVar {
- match self.kind {
- BoundRegionKind::BrAnon(var) => BoundVar::from_u32(var),
- _ => bug!("bound region is not anonymous"),
- }
- }
-}
-
impl BoundRegionKind {
pub fn is_named(&self) -> bool {
match *self {
FnPtr(PolyFnSig<'tcx>),
/// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`.
- Dynamic(&'tcx List<Binder<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>),
+ Dynamic(&'tcx List<Binder<'tcx, ExistentialPredicate<'tcx>>>, ty::Region<'tcx>),
/// The anonymous type of a closure. Used to represent the type of
/// `|a| a`.
/// A type representing the types stored inside a generator.
/// This should only appear in GeneratorInteriors.
- GeneratorWitness(Binder<&'tcx List<Ty<'tcx>>>),
+ GeneratorWitness(Binder<'tcx, &'tcx List<Ty<'tcx>>>),
/// The never type `!`.
Never,
// `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(TyKind<'_>, 24);
+static_assert_size!(TyKind<'_>, 32);
/// A closure can be modeled as a struct that looks like:
///
}
}
-impl<'tcx> Binder<ExistentialPredicate<'tcx>> {
+impl<'tcx> Binder<'tcx, ExistentialPredicate<'tcx>> {
pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> {
use crate::ty::ToPredicate;
match self.skip_binder() {
}
}
-impl<'tcx> List<ty::Binder<ExistentialPredicate<'tcx>>> {
+impl<'tcx> List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>> {
/// Returns the "principal `DefId`" of this set of existential predicates.
///
/// A Rust trait object type consists (in addition to a lifetime bound)
/// is `{Send, Sync}`, while there is no principal. These trait objects
/// have a "trivial" vtable consisting of just the size, alignment,
/// and destructor.
- pub fn principal(&self) -> Option<ty::Binder<ExistentialTraitRef<'tcx>>> {
+ pub fn principal(&self) -> Option<ty::Binder<'tcx, ExistentialTraitRef<'tcx>>> {
self[0]
.map_bound(|this| match this {
ExistentialPredicate::Trait(tr) => Some(tr),
#[inline]
pub fn projection_bounds<'a>(
&'a self,
- ) -> impl Iterator<Item = ty::Binder<ExistentialProjection<'tcx>>> + 'a {
+ ) -> impl Iterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> + 'a {
self.iter().filter_map(|predicate| {
predicate
.map_bound(|pred| match pred {
}
}
-pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>;
+pub type PolyTraitRef<'tcx> = Binder<'tcx, TraitRef<'tcx>>;
impl<'tcx> PolyTraitRef<'tcx> {
- pub fn self_ty(&self) -> Binder<Ty<'tcx>> {
+ pub fn self_ty(&self) -> Binder<'tcx, Ty<'tcx>> {
self.map_bound_ref(|tr| tr.self_ty())
}
}
}
-pub type PolyExistentialTraitRef<'tcx> = Binder<ExistentialTraitRef<'tcx>>;
+pub type PolyExistentialTraitRef<'tcx> = Binder<'tcx, ExistentialTraitRef<'tcx>>;
impl<'tcx> PolyExistentialTraitRef<'tcx> {
pub fn def_id(&self) -> DefId {
}
}
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(HashStable)]
+pub enum BoundVariableKind {
+ Ty(BoundTyKind),
+ Region(BoundRegionKind),
+ Const,
+}
+
/// 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<TraitRef>`). Note that when we instantiate,
+/// Binder<'tcx, TraitRef>`). Note that when we instantiate,
/// erase, or otherwise "discharge" these bound vars, we change the
-/// type from `Binder<T>` to just `T` (see
+/// type from `Binder<'tcx, T>` to just `T` (see
/// e.g., `liberate_late_bound_regions`).
///
/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-pub struct Binder<T>(T);
+pub struct Binder<'tcx, T>(T, &'tcx List<BoundVariableKind>);
-impl<T> Binder<T> {
+impl<'tcx, T> Binder<'tcx, T>
+where
+ T: TypeFoldable<'tcx>,
+{
/// Wraps `value` in a binder, asserting that `value` does not
/// 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<T>
- where
- T: TypeFoldable<'tcx>,
- {
+ pub fn dummy(value: T) -> Binder<'tcx, T> {
debug_assert!(!value.has_escaping_bound_vars());
- Binder(value)
+ Binder(value, ty::List::empty())
}
/// Wraps `value` in a binder, binding higher-ranked vars (if any).
- pub fn bind(value: T) -> Binder<T> {
- Binder(value)
+ pub fn bind(value: T, tcx: TyCtxt<'tcx>) -> Binder<'tcx, T> {
+ let mut collector = BoundVarsCollector::new();
+ value.visit_with(&mut collector);
+ Binder(value, collector.into_vars(tcx))
+ }
+
+ pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
+ if cfg!(debug_assertions) {
+ let mut validator = ValidateBoundVars::new(vars);
+ value.visit_with(&mut validator);
+ }
+ Binder(value, vars)
}
+}
+impl<'tcx, T> Binder<'tcx, T> {
/// Skips the binder and returns the "bound" value. This is a
/// risky thing to do because it's easy to get confused about
/// De Bruijn indices and the like. It is usually better to
self.0
}
- pub fn as_ref(&self) -> Binder<&T> {
- Binder(&self.0)
+ pub fn bound_vars(&self) -> &'tcx List<BoundVariableKind> {
+ self.1
+ }
+
+ pub fn as_ref(&self) -> Binder<'tcx, &T> {
+ Binder(&self.0, self.1)
}
- pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<U>
+ pub fn map_bound_ref_unchecked<F, U>(&self, f: F) -> Binder<'tcx, U>
+ where
+ F: FnOnce(&T) -> U,
+ {
+ let value = f(&self.0);
+ Binder(value, self.1)
+ }
+
+ pub fn map_bound_ref<F, U: TypeFoldable<'tcx>>(&self, f: F) -> Binder<'tcx, U>
where
F: FnOnce(&T) -> U,
{
self.as_ref().map_bound(f)
}
- pub fn map_bound<F, U>(self, f: F) -> Binder<U>
+ pub fn map_bound<F, U: TypeFoldable<'tcx>>(self, f: F) -> Binder<'tcx, U>
where
F: FnOnce(T) -> U,
{
- Binder(f(self.0))
+ let value = f(self.0);
+ if cfg!(debug_assertions) {
+ let mut validator = ValidateBoundVars::new(self.1);
+ value.visit_with(&mut validator);
+ }
+ Binder(value, self.1)
}
/// Wraps a `value` in a binder, using the same bound variables as the
/// don't actually track bound vars. However, semantically, it is different
/// because bound vars aren't allowed to change here, whereas they are
/// in `bind`. This may be (debug) asserted in the future.
- pub fn rebind<U>(&self, value: U) -> Binder<U> {
- Binder(value)
+ pub fn rebind<U>(&self, value: U) -> Binder<'tcx, U>
+ where
+ U: TypeFoldable<'tcx>,
+ {
+ if cfg!(debug_assertions) {
+ let mut validator = ValidateBoundVars::new(self.bound_vars());
+ value.visit_with(&mut validator);
+ }
+ Binder(value, self.1)
}
/// Unwraps and returns the value within, but only if it contains
/// 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_bound_vars<'tcx>(self) -> Option<T>
+ pub fn no_bound_vars(self) -> Option<T>
where
T: TypeFoldable<'tcx>,
{
if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
}
- /// Given two things that have the same binder level,
- /// and an operation that wraps on their contents, executes the operation
- /// and then wraps its result.
- ///
- /// `f` should consider bound regions at depth 1 to be free, and
- /// anything it produces with bound regions at depth 1 will be
- /// bound in the resulting return value.
- pub fn fuse<U, F, R>(self, u: Binder<U>, f: F) -> Binder<R>
- where
- F: FnOnce(T, U) -> R,
- {
- Binder(f(self.0, u.0))
- }
-
/// Splits the contents into two things that share the same binder
/// level as the original, returning two distinct binders.
///
/// `f` should consider bound regions at depth 1 to be free, and
/// anything it produces with bound regions at depth 1 will be
/// bound in the resulting return values.
- pub fn split<U, V, F>(self, f: F) -> (Binder<U>, Binder<V>)
+ pub fn split<U, V, F>(self, f: F) -> (Binder<'tcx, U>, Binder<'tcx, V>)
where
F: FnOnce(T) -> (U, V),
{
let (u, v) = f(self.0);
- (Binder(u), Binder(v))
+ (Binder(u, self.1), Binder(v, self.1))
}
}
-impl<T> Binder<Option<T>> {
- pub fn transpose(self) -> Option<Binder<T>> {
- self.0.map(Binder)
+impl<'tcx, T> Binder<'tcx, Option<T>> {
+ pub fn transpose(self) -> Option<Binder<'tcx, T>> {
+ let bound_vars = self.1;
+ self.0.map(|v| Binder(v, bound_vars))
}
}
pub return_ty: Ty<'tcx>,
}
-pub type PolyGenSig<'tcx> = Binder<GenSig<'tcx>>;
+pub type PolyGenSig<'tcx> = Binder<'tcx, GenSig<'tcx>>;
/// Signature of a function type, which we have arbitrarily
/// decided to use to refer to the input/output types.
}
}
-pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>;
+pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>;
impl<'tcx> PolyFnSig<'tcx> {
#[inline]
- pub fn inputs(&self) -> Binder<&'tcx [Ty<'tcx>]> {
- self.map_bound_ref(|fn_sig| fn_sig.inputs())
+ pub fn inputs(&self) -> Binder<'tcx, &'tcx [Ty<'tcx>]> {
+ self.map_bound_ref_unchecked(|fn_sig| fn_sig.inputs())
}
#[inline]
- pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> {
+ pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> {
self.map_bound_ref(|fn_sig| fn_sig.inputs()[index])
}
- pub fn inputs_and_output(&self) -> ty::Binder<&'tcx List<Ty<'tcx>>> {
+ pub fn inputs_and_output(&self) -> ty::Binder<'tcx, &'tcx List<Ty<'tcx>>> {
self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output)
}
#[inline]
- pub fn output(&self) -> ty::Binder<Ty<'tcx>> {
+ pub fn output(&self) -> ty::Binder<'tcx, Ty<'tcx>> {
self.map_bound_ref(|fn_sig| fn_sig.output())
}
pub fn c_variadic(&self) -> bool {
}
}
-pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<FnSig<'tcx>>>;
+pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub ty: Ty<'tcx>,
}
-pub type PolyExistentialProjection<'tcx> = Binder<ExistentialProjection<'tcx>>;
+pub type PolyExistentialProjection<'tcx> = Binder<'tcx, ExistentialProjection<'tcx>>;
impl<'tcx> ExistentialProjection<'tcx> {
/// Extracts the underlying existential trait reference from this projection.