docs/_docs/contributing/architecture/symbols.md
As discussed previously, dotc maintains time-indexed views of various
compiler artifacts. The following sections discuss how they are managed in the compiler.
Defined in Symbols, a Symbol is a unique identifier for a definition (e.g. a method,
type, or field). A ClassSymbol extends Symbol and represents either a
class, or a trait, or an object. A Symbol can even refer to non-Scala entities,
such as from the Java standard library.
Traditionally, compilers store context-dependent data in a symbol table.
Where a symbol then is the central reference to address context-dependent data.
dotc instead uses a phase-indexed function (known as
a Denotation) to compute views of definitions across phases,
as many of attributes associated with definitions are phase-dependent. For example:
Additionally, symbols are not suitable to be used as a reference to
a definition in another compilation unit.
In the context of incremental compilation, a symbol from
an external compilation unit may be deleted or changed, making the reference
stale. To counter this, dotc types trees of cross-module references with either
a TermRef or TypeRef. A reference type contains a prefix type and a name.
The denotation that the type refers to is established dynamically based on
these fields.
On its own a Symbol has no structure. Its semantic meaning is given by being associated
with a Denotation.
A denotation is the result of resolving a name during a given period, containing the information
describing some entity (either a term or type), indexed by phase. Denotations usually have a
reference to a selected symbol, but not always, for example if the denotation is overloaded,
i.e. a MultiDenotation.
All definition symbols will contain a SymDenotation. The denotation, in turn, contains:
info method)NotAMethod).A class symbol will instead be associated with a ClassDenotation, which extends SymDenotation
with some additional fields specific for classes.