Expand description
Β§typeck: check phase
Within the check phase of type check, we check each item one at a time (bodies of function expressions are checked as part of the containing function). Inference is used to supply types wherever they are unknown.
By far the most complex case is checking the body of a function. This can be broken down into several distinct phases:
-
gather: creates type variables to represent the type of each local variable and pattern binding.
-
main: the main pass does the lionβs share of the work: it determines the types of all expressions, resolves methods, checks for most invalid conditions, and so forth. In some cases, where a type is unknown, it may create a type or region variable and use that as the type of an expression.
In the process of checking, various constraints will be placed on these type variables through the subtyping relationships requested through the
demand
module. Theinfer
module is in charge of resolving those constraints. -
regionck: after main is complete, the regionck pass goes over all types looking for regions and making sure that they did not escape into places where they are not in scope. This may also influence the final assignments of the various region variables if there is some flexibility.
-
writeback: writes the final types within a function body, replacing type variables with their final inferred types. These final types are written into the
tcx.node_types
table, which should never contain any reference to a type variable.
Β§Intermediate types
While type checking a function, the intermediate types for the
expressions, blocks, and so forth contained within the function are
stored in fcx.node_types
and fcx.node_args
. These types
may contain unresolved type variables. After type checking is
complete, the functions in the writeback module are used to take the
types from this table, resolve them, and then write them into their
permanent home in the type context tcx
.
This means that during inferencing you should use fcx.write_ty()
and fcx.expr_ty()
/ fcx.node_ty()
to write/obtain the types of
nodes within the function.
The types of top-level items, which never contain unbound type
variables, are stored directly into the tcx
typeck_results.
N.B., a type variable is not the same thing as a type parameter. A
type variable is an instance of a type parameter. That is,
given a generic function fn foo<T>(t: T)
, while checking the
function foo
, the type ty_param(0)
refers to the type T
, which
is treated in abstract. However, when foo()
is called, T
will be
instantiated with a fresh type variable N
. This variable will
eventually be resolved to some concrete type (which might itself be
a type parameter).
Modules§
- check π
- compare_
impl_ πitem - entry π
- Type-checking for the rust-intrinsic intrinsics that the compiler exposes.
- region πThis file builds up the
ScopeTree
, which describes the parent links in the region hierarchy.
Functions§
- adt_
async_ πdestructor - adt_
destructor π - Emit an error when encountering two or more non-zero-sized fields in a transparent enum.
- bad_
variant_ πcount Emit an error when encountering two or more variants in a transparent enum. - Re-sugar
ty::GenericPredicates
in a way suitable to be used in structured suggestions. - fn_
sig_ πsuggestion Return placeholder code for the given function. - Forbid defining intrinsics in Rust code, as they must always be defined by the compiler.
- Given a
DefId
for an opaque type in return position, find its parent itemβs return expressions. - missing_
items_ πerr - suggestion_
signature πReturn placeholder code for the given associated item. Similar toty::AssocItem::suggestion
, but appropriate for use as the code snippet of a structured suggestion.