You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> (The following is work in progress), adapted from dotty.epfl.ch
11
-
12
-
## Symbols and SymDenotations
13
-
14
-
- why symbols are not enough: their contents change all the time
15
-
- reference: string + sig
16
-
17
-
18
-
`dotc` is different from most other compilers in that it is centered around the idea of
19
-
maintaining views of various artifacts associated with code. These views are indexed
20
-
by time.
21
-
22
-
A symbol refers to a definition in a source program. Traditionally,
23
-
compilers store context-dependent data in a _symbol table_. The
24
-
symbol then is the central reference to address context-dependent
25
-
data. But for the requirements of `dotc` it turns out that symbols are
26
-
both too little and too much for this task.
27
-
28
-
**Too little:** The attributes of a symbol depend on the phase. Examples:
29
-
Types are gradually simplified by several phases. Owners are changed
30
-
in phases `LambdaLift` (when methods are lifted out to an enclosing
31
-
class) and Flatten (when all classes are moved to top level). Names
32
-
are changed when private members need to be accessed from outside
33
-
their class (for instance from a nested class or a class implementing
34
-
a trait). So a functional compiler, a `Symbol` by itself met mean
35
-
much. Instead we are more interested in the attributes of a symbol at
36
-
a given phase.
37
-
38
-
**Too much:** If a symbol is used to refer to a definition in another
39
-
compilation unit, we get problems for incremental recompilation. The
40
-
unit containing the symbol might be changed and recompiled, which
41
-
might mean that the definition referred to by the symbol is deleted or
42
-
changed. This leads to the problem of stale symbols that refer to
43
-
definitions that no longer exist in this form. Scala 2 compiler tried to
44
-
address this problem by _rebinding_ symbols appearing in certain cross
45
-
module references, but it turned out to be too difficult to do this
46
-
reliably for all kinds of references. Scala 3 compiler attacks the problem at
47
-
the root instead. The fundamental problem is that symbols are too
48
-
specific to serve as a cross-module reference in a system with
49
-
incremental compilation. They refer to a particular definition, but
50
-
that definition may not persist unchanged after an edit.
51
-
52
-
`dotc` uses instead a different approach: A cross module reference is
53
-
always type, either a `TermRef` or `TypeRef`. A reference type contains
54
-
a prefix type and a name. The definition the type refers to is established
55
-
dynamically based on these fields.
56
-
57
-
58
-
<!-- a system where sources can be recompiled at any instance,
59
-
60
-
the concept of a `Denotation`.
61
-
62
-
Since definitions are transformed by phases, -->
10
+
As discussed previously, `dotc`[maintains time-indexed views][arch-time] of various
11
+
compiler artifacts. The following sections discuss how they are managed in the compiler.
63
12
64
13
## Symbols
65
-
`dotc/core/Symbols.scala`
66
-
67
-
Symbols are references to definitions (e.g. of variables, fields, classes). Symbols can be used to refer to definitions for which we don't have ASTs (for example, from the Java standard library).
68
-
69
-
`NoSymbol` is used to indicate the lack of a symbol.
70
-
71
-
Symbols uniquely identify definitions, but they don't say what the definitions *mean*. To understand the meaning of a symbol
72
-
we need to look at its *denotation* (specially for symbols, a `SymDenotation`).
73
-
74
-
Symbols can not only represent terms, but also types (hence the `isTerm`/`isType` methods in the `Symbol` class).
75
-
76
-
## ClassSymbol
77
-
78
-
`ClassSymbol` represents either a `class`, or a `trait`, or an `object`. For example, an object
79
-
```scala
80
-
objectO {
81
-
vals=1
82
-
}
83
-
```
84
-
is represented (after `Typer`) as
85
-
```scala
86
-
classO$ { this:O.type=>
87
-
vals=1
88
-
}
89
-
valO=newO$
90
-
```
91
-
where we have a type symbol for `class O$` and a term symbol for `val O`. Notice the use of the selftype `O.type` to indicate that `this` has a singleton type.
92
-
93
-
94
-
## SymDenotation
95
-
`dotc/core/SymDenotations.scala`
96
-
97
-
Symbols contain `SymDenotation`s. The denotation, in turn, refers to:
98
-
99
-
* the source symbol (so the linkage is cyclic)
100
-
* the "owner" of the symbol:
101
-
- if the symbol is a variable, the owner is the enclosing method
102
-
- if it's a field, the owner is the enclosing class
103
-
- if it's a class, then the owner is the enclosing class
104
-
* a set of flags that contain semantic information about the definition (e.g. whether it's a trait or mutable). Flags are defined in `Flags.scala`.
105
-
* the type of the definition (through the `info` method)
106
-
107
-
## Denotation
108
-
[Comment with a few details:][Denotations2]
109
-
110
-
A `Denotation` is the result of a name lookup during a given period
111
-
112
-
* Most properties of symbols are now in the denotation (name, type, owner,
113
-
etc.)
114
-
* Denotations usually have a reference to the selected symbol
115
-
* Denotations may be overloaded (`MultiDenotation`). In this case the symbol
116
-
may be `NoSymbol` (the two variants have symbols).
117
-
* Non-overloaded denotations have an `info`
118
-
119
-
Denotations of methods have a [signature][Signature1], which
120
-
uniquely identifies overloaded methods.
121
-
122
-
### Denotation vs. SymDenotation
123
-
A `SymDenotation` is an extended denotation that has symbol-specific properties
124
-
(that may change over phases)
125
-
*`flags`
126
-
*`annotations`
127
-
*`info`
128
14
129
-
`SymDenotation` implements lazy types (similar to scalac). The type completer
130
-
assigns the denotation's `info`.
15
+
Defined in [Symbols], a `Symbol` is a unique identifier for a definition (e.g. a method,
16
+
type, or field). A `ClassSymbol` extends `Symbol` and represents either a
17
+
`class`, or a `trait`, or an `object`. A `Symbol` can even refer to non-Scala entities,
18
+
such as from the Java standard library.
19
+
20
+
## Definitions are Dynamic
21
+
22
+
Traditionally, compilers store context-dependent data in a _symbol table_.
23
+
Where a symbol then is the central reference to address context-dependent data.
24
+
`dotc` makes a change to instead use a phase indexed function (known as
25
+
a [Denotation][Denotations]) to compute views of definitions accross phases,
26
+
as many of attributes associated with definitions are phase-dependent. For example:
27
+
- types are gradually simplified by several phases,
28
+
- owners change in [lambdaLift] (local methods are lifted to an enclosing class)
29
+
and [flatten] (when inner classes are moved to the top level)
30
+
- Names are changed when private members need to be accessed from outside
31
+
their class (for instance from a nested class or a class implementing
32
+
a trait).
33
+
34
+
Additionally, symbols are not suitable to be used as a reference to
35
+
a definition in another [compilation unit][CompilationUnit].
36
+
In the context of incremental compilation, a referred symbol from
37
+
an external compilation unit may be deleted or changed, making the reference
38
+
stale. To counter this, `dotc` types trees of cross module references with either
39
+
a `TermRef` or `TypeRef`. A reference type contains a prefix type and a name.
40
+
The denotation that the type refers to is established dynamically based on
41
+
these fields.
42
+
43
+
## Denotations
44
+
45
+
On its own a `Symbol` has no structure. Its semantic meaning is given by being associated
46
+
with a [Denotation][Denotations].
47
+
48
+
A denotation is the result of resolving a name during a given period, containing the information
49
+
describing some entity (either a term or type), indexed by phase. Denotations usually have a
50
+
reference to a selected symbol, but not always, for example if the denotation is overloaded,
51
+
i.e. a `MultiDenotation`.
52
+
53
+
### SymDeno
C182
tations
54
+
All definition symbols will contain a `SymDenotation`. The denotation, in turn, contains:
55
+
- a reverse link to the source symbol
56
+
- a reference to the enclosing symbol that defined the source symbol:
57
+
- for a local variable, the enclosing method
58
+
- for a field or class, the enclosing class
59
+
- a set of [flags], describing the definition (e.g. whether it's a trait or mutable).
60
+
- the type of the definition (through the `info` method)
61
+
- a [signature][Signature1], which uniquely identifies overloaded methods (or else `NotAMethod`).
62
+
- and more.
63
+
64
+
A class symbol will instead be associated with a `ClassDenotation`, which extends `SymDenotation`
0 commit comments