#![feature(min_specialization)]
+#![feature(rustc_attrs)]
#[macro_use]
extern crate bitflags;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
+use smallvec::SmallVec;
use std::fmt;
+use std::fmt::Debug;
+use std::hash::Hash;
use std::mem::discriminant;
+pub mod codec;
+pub mod sty;
+
+pub use codec::*;
+pub use sty::*;
+
+pub trait Interner {
+ type AdtDef: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type SubstsRef: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type DefId: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type Ty: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type Const: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type Region: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type TypeAndMut: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type Mutability: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type Movability: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type PolyFnSig: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type ListBinderExistentialPredicate: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type BinderListTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type ListTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type ProjectionTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type ParamTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type BoundTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type PlaceholderType: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type InferTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type DelaySpanBugEmitted: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type PredicateKind: Clone + Debug + Hash + PartialEq + Eq;
+ type AllocId: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+
+ type EarlyBoundRegion: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type BoundRegion: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type FreeRegion: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type RegionVid: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type PlaceholderRegion: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+}
+
+pub trait InternAs<T: ?Sized, R> {
+ type Output;
+ fn intern_with<F>(self, f: F) -> Self::Output
+ where
+ F: FnOnce(&T) -> R;
+}
+
+impl<I, T, R, E> InternAs<[T], R> for I
+where
+ E: InternIteratorElement<T, R>,
+ I: Iterator<Item = E>,
+{
+ type Output = E::Output;
+ fn intern_with<F>(self, f: F) -> Self::Output
+ where
+ F: FnOnce(&[T]) -> R,
+ {
+ E::intern_with(self, f)
+ }
+}
+
+pub trait InternIteratorElement<T, R>: Sized {
+ type Output;
+ fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output;
+}
+
+impl<T, R> InternIteratorElement<T, R> for T {
+ type Output = R;
+ fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(
+ mut iter: I,
+ f: F,
+ ) -> Self::Output {
+ // This code is hot enough that it's worth specializing for the most
+ // common length lists, to avoid the overhead of `SmallVec` creation.
+ // Lengths 0, 1, and 2 typically account for ~95% of cases. If
+ // `size_hint` is incorrect a panic will occur via an `unwrap` or an
+ // `assert`.
+ match iter.size_hint() {
+ (0, Some(0)) => {
+ assert!(iter.next().is_none());
+ f(&[])
+ }
+ (1, Some(1)) => {
+ let t0 = iter.next().unwrap();
+ assert!(iter.next().is_none());
+ f(&[t0])
+ }
+ (2, Some(2)) => {
+ let t0 = iter.next().unwrap();
+ let t1 = iter.next().unwrap();
+ assert!(iter.next().is_none());
+ f(&[t0, t1])
+ }
+ _ => f(&iter.collect::<SmallVec<[_; 8]>>()),
+ }
+ }
+}
+
+impl<'a, T, R> InternIteratorElement<T, R> for &'a T
+where
+ T: Clone + 'a,
+{
+ type Output = R;
+ fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
+ // This code isn't hot.
+ f(&iter.cloned().collect::<SmallVec<[_; 8]>>())
+ }
+}
+
+impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
+ type Output = Result<R, E>;
+ fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(
+ mut iter: I,
+ f: F,
+ ) -> Self::Output {
+ // This code is hot enough that it's worth specializing for the most
+ // common length lists, to avoid the overhead of `SmallVec` creation.
+ // Lengths 0, 1, and 2 typically account for ~95% of cases. If
+ // `size_hint` is incorrect a panic will occur via an `unwrap` or an
+ // `assert`, unless a failure happens first, in which case the result
+ // will be an error anyway.
+ Ok(match iter.size_hint() {
+ (0, Some(0)) => {
+ assert!(iter.next().is_none());
+ f(&[])
+ }
+ (1, Some(1)) => {
+ let t0 = iter.next().unwrap()?;
+ assert!(iter.next().is_none());
+ f(&[t0])
+ }
+ (2, Some(2)) => {
+ let t0 = iter.next().unwrap()?;
+ let t1 = iter.next().unwrap()?;
+ assert!(iter.next().is_none());
+ f(&[t0, t1])
+ }
+ _ => f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?),
+ })
+ }
+}
+
bitflags! {
/// Flags that we track on types. These flags are propagated upwards
/// through the type during type construction, so that we can quickly check
}
}
}
+
+rustc_index::newtype_index! {
+ /// "Universes" are used during type- and trait-checking in the
+ /// presence of `for<..>` binders to control what sets of names are
+ /// visible. Universes are arranged into a tree: the root universe
+ /// contains names that are always visible. Each child then adds a new
+ /// set of names that are visible, in addition to those of its parent.
+ /// We say that the child universe "extends" the parent universe with
+ /// new names.
+ ///
+ /// To make this more concrete, consider this program:
+ ///
+ /// ```ignore (illustrative)
+ /// struct Foo { }
+ /// fn bar<T>(x: T) {
+ /// let y: for<'a> fn(&'a u8, Foo) = ...;
+ /// }
+ /// ```
+ ///
+ /// The struct name `Foo` is in the root universe U0. But the type
+ /// parameter `T`, introduced on `bar`, is in an extended universe U1
+ /// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside
+ /// of `bar`, we cannot name `T`. Then, within the type of `y`, the
+ /// region `'a` is in a universe U2 that extends U1, because we can
+ /// name it inside the fn type but not outside.
+ ///
+ /// Universes are used to do type- and trait-checking around these
+ /// "forall" binders (also called **universal quantification**). The
+ /// idea is that when, in the body of `bar`, we refer to `T` as a
+ /// type, we aren't referring to any type in particular, but rather a
+ /// kind of "fresh" type that is distinct from all other types we have
+ /// actually declared. This is called a **placeholder** type, and we
+ /// use universes to talk about this. In other words, a type name in
+ /// universe 0 always corresponds to some "ground" type that the user
+ /// declared, but a type name in a non-zero universe is a placeholder
+ /// type -- an idealized representative of "types in general" that we
+ /// use for checking generic functions.
+ pub struct UniverseIndex {
+ DEBUG_FORMAT = "U{}",
+ }
+}
+
+impl UniverseIndex {
+ pub const ROOT: UniverseIndex = UniverseIndex::from_u32(0);
+
+ /// Returns the "next" universe index in order -- this new index
+ /// is considered to extend all previous universes. This
+ /// corresponds to entering a `forall` quantifier. So, for
+ /// example, suppose we have this type in universe `U`:
+ ///
+ /// ```ignore (illustrative)
+ /// for<'a> fn(&'a u32)
+ /// ```
+ ///
+ /// Once we "enter" into this `for<'a>` quantifier, we are in a
+ /// new universe that extends `U` -- in this new universe, we can
+ /// name the region `'a`, but that region was not nameable from
+ /// `U` because it was not in scope there.
+ pub fn next_universe(self) -> UniverseIndex {
+ UniverseIndex::from_u32(self.private.checked_add(1).unwrap())
+ }
+
+ /// Returns `true` if `self` can name a name from `other` -- in other words,
+ /// if the set of names in `self` is a superset of those in
+ /// `other` (`self >= other`).
+ pub fn can_name(self, other: UniverseIndex) -> bool {
+ self.private >= other.private
+ }
+
+ /// Returns `true` if `self` cannot name some names from `other` -- in other
+ /// words, if the set of names in `self` is a strict subset of
+ /// those in `other` (`self < other`).
+ pub fn cannot_name(self, other: UniverseIndex) -> bool {
+ self.private < other.private
+ }
+}
+
+impl<CTX> HashStable<CTX> for UniverseIndex {
+ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+ self.private.hash_stable(ctx, hasher);
+ }
+}