Set of traits which are used to emulate the inherent impls that are present in rustc_middle.
It is customary to glob-import rustc_type_ir::inherent::* to bring all of these traits into
scope when programming in interner-agnostic settings, and to avoid importing any of these
directly elsewhere (i.e. specify the full path for an implementation downstream).
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<I, TraitRef>). Note that when we instantiate,
erase, or otherwise “discharge” these bound vars, we change the
type from Binder<I, T> to just T (see
e.g., liberate_late_bound_regions).
A “canonicalized” type V is one where all free inference
variables have been rewritten to “canonical vars”. These are
numbered starting from 0 in order of first appearance.
Information about a canonical variable that is included with the
canonical value. This is sufficient information for code to create
a copy of the canonical value in some other inference context,
with fresh inference variables replacing the canonical values.
A set of values corresponding to the canonical variables from some
Canonical. You can give these values to
canonical_value.instantiate to instantiate them into the canonical
value at the right places.
A De Bruijn index is a standard means of representing
regions (and perhaps later types) in a higher-ranked setting. In
particular, imagine a type like this:
Similar to super::Binder except that it tracks early bound generics, i.e. struct Foo<T>(T)
needs T instantiated immediately. This type primarily exists to avoid forgetting to call
instantiate.
Encodes that a must be a subtype of b. The a_is_expected flag indicates
whether the a type is the type that we should label as “expected” when
presenting user diagnostics.
Flags that we track on types. These flags are propagated upwards
through the type during type construction, so that we can quickly check
whether the type has various kinds of types in it without recursing
over the type itself.
“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.
A helper type that you can wrap round your own type in order to automatically
cache the stable hash, type flags and debruijn index on creation and
not recompute it whenever the information is needed.
This is only done in incremental mode. You can also opt out of caching by using
StableHash::ZERO for the hash, in which case the hash gets computed each time.
This is useful if you have values that you intern but never (can?) use for stable
hashing.
Rust actually has more than one category of type variables;
notably, the type variables we create for literals (e.g., 22 or
22.) can only be instantiated with integral/float types (e.g.,
usize or f32). In order to faithfully reproduce a type, we need to
know what set of types a given type variable can be unified with.
Describes the “kind” of the canonical variable. This is a “kind”
in the type-theory sense of the term – i.e., a “meta” type system
that analyzes type-like values.
Represents the various closure traits in the language. This
will determine the type of the environment (self, in the
desugaring) argument that the closure expects.
Polarity for a trait predicate. May either be negative or positive.
Distinguished from ImplPolarity since we never compute goals with
“reservation” level.
Representation of regions. Note that the NLL checker uses a distinct
representation of regions. For this reason, it internally replaces all the
regions with inference variables – the index of the variable is then used
to index into internal NLL data structures. See rustc_const_eval::borrow_check
module for more information.
The current typing mode of an inference context. We unfortunately have some
slightly different typing rules depending on the current context. See the
doc comment for each variant for how and why they are used.
Imagine you have a function F: FnOnce(&[T]) -> R, plus an iterator iter
that produces T items. You could combine them with
f(&iter.collect::<Vec<_>>()), but this requires allocating memory for the
Vec.