Identifiers in the compiler
If you have read the few previous chapters, you now know that rustc
uses
many different intermediate representations to perform different kinds of analyses.
However, like in every data structure, you need a way to traverse the structure
and refer to other elements. In this chapter, you will find information on the
different identifiers rustc
uses for each intermediate representation.
In the AST
A NodeId
is an identifier number that uniquely identifies an AST node within
a crate. Every node in the AST has its own NodeId
, including top-level items
such as structs, but also individual statements and expressions.
However, because they are absolute within a crate, adding or removing a single
node in the AST causes all the subsequent NodeId
s to change. This renders
NodeId
s pretty much useless for incremental compilation, where you want as
few things as possible to change.
NodeId
s are used in all the rustc
bits that operate directly on the AST,
like macro expansion and name resolution.
In the HIR
The HIR uses a bunch of different identifiers that coexist and serve different purposes.
-
A
DefId
, as the name suggests, identifies a particular definition, or top-level item, in a given crate. It is composed of two parts: aCrateNum
which identifies the crate the definition comes from, and aDefIndex
which identifies the definition within the crate. UnlikeHirId
s, there isn't aDefId
for every expression, which makes them more stable across compilations. -
A
LocalDefId
is basically aDefId
that is known to come from the current crate. This allows us to drop theCrateNum
part, and use the type system to ensure that only local definitions are passed to functions that expect a local definition. -
A
HirId
uniquely identifies a node in the HIR of the current crate. It is composed of two parts: anowner
and alocal_id
that is unique within theowner
. This combination makes for more stable values which are helpful for incremental compilation. UnlikeDefId
s, aHirId
can refer to fine-grained entities like expressions, but stays local to the current crate. -
A
BodyId
identifies a HIRBody
in the current crate. It is currently only a wrapper around aHirId
. For more info about HIR bodies, please refer to the HIR chapter.
These identifiers can be converted into one another through the HIR map. See the HIR chapter for more detailed information.
In the MIR
-
BasicBlock
identifies a basic block. It points to an instance ofBasicBlockData
, which can be retrieved by indexing intoBody.basic_blocks
. -
Local
identifies a local variable in a function. Its associated data is inLocalDecl
, which can be retrieved by indexing intoBody.local_decls
. -
FieldIdx
identifies a struct's, union's, or enum variant's field. It is used as a "projection" inPlace
. -
SourceScope
identifies a name scope in the original source code. Used for diagnostics and for debuginfo in debuggers. It points to an instance ofSourceScopeData
, which can be retrieved by indexing intoBody.source_scopes
. -
Promoted
identifies a promoted constant within another item (related to const evaluation). Note: it is unique only locally within the item, so it should be associated with aDefId
.GlobalId
will give you a more specific identifier. -
GlobalId
identifies a global variable: aconst
, astatic
, aconst fn
where all arguments are zero-sized types, or a promoted constant. -
Location
represents the location in the MIR of a statement or terminator. It identifies the block (usingBasicBlock
) and the index of the statement or terminator in the block.