introduce Universe
struct
This commit is contained in:
parent
a85417f593
commit
803bd76127
@ -1306,6 +1306,68 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// "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. But when you enter into
|
||||
/// some subuniverse, then it may add names that are only visible
|
||||
/// within that subtree (but it can still name the names of its
|
||||
/// ancestor universes).
|
||||
///
|
||||
/// To make this more concrete, consider this program:
|
||||
///
|
||||
/// ```
|
||||
/// 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 a subuniverse 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 subuniverse U2 of U1, because we can name it
|
||||
/// inside the fn type but not outside.
|
||||
///
|
||||
/// Universes are related to **skolemization** -- which is a way of
|
||||
/// doing 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 **skolemized** 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 skolemized type -- an
|
||||
/// idealized representative of "types in general" that we use for
|
||||
/// checking generic functions.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct UniverseIndex(u32);
|
||||
|
||||
impl UniverseIndex {
|
||||
/// The root universe, where things that the user defined are
|
||||
/// visible.
|
||||
pub fn root() -> UniverseIndex {
|
||||
UniverseIndex(0)
|
||||
}
|
||||
|
||||
/// A "subuniverse" corresponds to being inside a `forall` quantifier.
|
||||
/// So, for example, suppose we have this type in universe `U`:
|
||||
///
|
||||
/// ```
|
||||
/// for<'a> fn(&'a u32)
|
||||
/// ```
|
||||
///
|
||||
/// Once we "enter" into this `for<'a>` quantifier, we are in a
|
||||
/// subuniverse of `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 subuniverse(self) -> UniverseIndex {
|
||||
UniverseIndex(self.0 + 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// When type checking, we use the `ParamEnv` to track
|
||||
/// details about the set of where-clauses that are in scope at this
|
||||
/// particular point.
|
||||
|
Loading…
x
Reference in New Issue
Block a user