Skip to content

Commit 803bd76

Browse files
nikomatsakissgrif
authored andcommitted
introduce Universe struct
1 parent a85417f commit 803bd76

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

src/librustc/ty/mod.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,68 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
13061306
}
13071307
}
13081308

1309+
/// "Universes" are used during type- and trait-checking in the
1310+
/// presence of `for<..>` binders to control what sets of names are
1311+
/// visible. Universes are arranged into a tree: the root universe
1312+
/// contains names that are always visible. But when you enter into
1313+
/// some subuniverse, then it may add names that are only visible
1314+
/// within that subtree (but it can still name the names of its
1315+
/// ancestor universes).
1316+
///
1317+
/// To make this more concrete, consider this program:
1318+
///
1319+
/// ```
1320+
/// struct Foo { }
1321+
/// fn bar<T>(x: T) {
1322+
/// let y: for<'a> fn(&'a u8, Foo) = ...;
1323+
/// }
1324+
/// ```
1325+
///
1326+
/// The struct name `Foo` is in the root universe U0. But the type
1327+
/// parameter `T`, introduced on `bar`, is in a subuniverse U1 --
1328+
/// i.e., within `bar`, we can name both `T` and `Foo`, but outside of
1329+
/// `bar`, we cannot name `T`. Then, within the type of `y`, the
1330+
/// region `'a` is in a subuniverse U2 of U1, because we can name it
1331+
/// inside the fn type but not outside.
1332+
///
1333+
/// Universes are related to **skolemization** -- which is a way of
1334+
/// doing type- and trait-checking around these "forall" binders (also
1335+
/// called **universal quantification**). The idea is that when, in
1336+
/// the body of `bar`, we refer to `T` as a type, we aren't referring
1337+
/// to any type in particular, but rather a kind of "fresh" type that
1338+
/// is distinct from all other types we have actually declared. This
1339+
/// is called a **skolemized** type, and we use universes to talk
1340+
/// about this. In other words, a type name in universe 0 always
1341+
/// corresponds to some "ground" type that the user declared, but a
1342+
/// type name in a non-zero universe is a skolemized type -- an
1343+
/// idealized representative of "types in general" that we use for
1344+
/// checking generic functions.
1345+
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1346+
pub struct UniverseIndex(u32);
1347+
1348+
impl UniverseIndex {
1349+
/// The root universe, where things that the user defined are
1350+
/// visible.
1351+
pub fn root() -> UniverseIndex {
1352+
UniverseIndex(0)
1353+
}
1354+
1355+
/// A "subuniverse" corresponds to being inside a `forall` quantifier.
1356+
/// So, for example, suppose we have this type in universe `U`:
1357+
///
1358+
/// ```
1359+
/// for<'a> fn(&'a u32)
1360+
/// ```
1361+
///
1362+
/// Once we "enter" into this `for<'a>` quantifier, we are in a
1363+
/// subuniverse of `U` -- in this new universe, we can name the
1364+
/// region `'a`, but that region was not nameable from `U` because
1365+
/// it was not in scope there.
1366+
pub fn subuniverse(self) -> UniverseIndex {
1367+
UniverseIndex(self.0 + 1)
1368+
}
1369+
}
1370+
13091371
/// When type checking, we use the `ParamEnv` to track
13101372
/// details about the set of where-clauses that are in scope at this
13111373
/// particular point.

0 commit comments

Comments
 (0)