Skip to content

Refactor: Sync Contributing section from Scala-lang Guide to Dotty website #17459

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added docs/_assets/images/contribution/breakpoint.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/_assets/images/contribution/call-stack.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/_assets/images/contribution/import-build.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/_assets/images/contribution/toolbar.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions docs/_docs/contributing/architecture/context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
layout: doc-page
title: Contexts
---

`dotc` has almost no global state (with the exception of the name table,
which hashes strings into unique names). Instead, all
essential bits of information that can vary over a compiler [run](./lifecycle.md) are collected
in a `Context` (defined in [Contexts]).

Most methods in the compiler depend on an implicit anonymous `Context` parameter,
and a typical definition looks like the following:
```scala
import dotty.tools.dotc.Contexts.{Context, ctx}

def doFoo(using Context): Unit =
val current = ctx.run // access the Context parameter with `ctx`
```

## Memory Leaks
> **Careful:** Contexts can be heavy so beware of memory leaks

It is good practice to ensure that implicit contexts are not
captured in closures or other long-lived objects, in order to avoid space leaks
in the case where a closure can survive several compiler runs (e.g. a
lazy completer for a library class that is never required). In that case, the
convention is that the `Context` be an explicit parameter, to track its usage.

## Context Properties

| Context property | description |
|-------------------|----------------------------------------|
| `compilationUnit` | current compilation unit |
| `phase` | current phase |
| `run` | current run |
| `period` | current period |
| `settings` | the config passed to the compiler |
| `reporter` | operations for logging errors/warnings |
| `definitions` | the standard built in definitions |
| `platform` | operations for the underlying platform |
| `tree` | current tree |
| `scope` | current scope |
| `typer` | current typer |
| `owner` | current owner symbol |
| `outer` | outer Context |
| `mode` | type checking mode |
| `typerState` | |
| `searchHistory` | |
| `implicits` | |
| ... | and so on |


[Contexts]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Contexts.scala
14 changes: 14 additions & 0 deletions docs/_docs/contributing/architecture/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
layout: index
title: High Level Architecture
---

This chapter of the guide describes the architecture and concepts of `dotc`,
the Scala 3 compiler, including answers to questions such as:
- "What are the transformations that happen to my code?"
- "How do I run a compiler programatically?"
- "What are symbols, denotations, names and types?"
- "What is a compiler phase?"
- "What is the compiler Context?"

and many more.
90 changes: 90 additions & 0 deletions docs/_docs/contributing/architecture/lifecycle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
layout: doc-page
title: Compiler Overview
---

At a high level, `dotc` is an interactive compiler (see [what is a compiler?](../index.md#what-is-a-compiler)),
and can be invoked frequently, for example to answer questions for an IDE, provide REPL completions,
or to manage incremental builds and more. Each of these use cases requires a customised
workflow, but sharing a common core.

## Introducing the Compiler's Lifecycle

#### Core
Customisation is provided by extending the [Compiler] class, which maintains an ordered
list of [phases][Phases], and how to [run][Run] them. Each interaction with a compiler
creates a new run, which is a complete iteration of the compiler's phases over a list
of input sources. Each run has the capability to create new definitions or
invalidate older ones, and `dotc` can [track these changes over time](../architecture/time.md).

#### Runs
During a run, the input sources are converted to [compilation units][CompilationUnit] (i.e. the abstraction of
compiler state associated with each input source); then iteratively: a single phase is applied to
every compilation unit before progressing to the next phase.

#### Phases
A phase is an abstract transformation over a compilation unit, it is usually responsible
for transforming the trees and types representing the code of a source file. Some phases of
the compiler are:
- `parser`, which converts text that matches Scala's
[syntax] into abstract syntax trees, ASTs
- `typer`, which checks that trees conform to expected types
- `erasure`, which retypes a more simplified program into one that has the same types as the JVM.
- `genBCode`, the JVM backend, which converts erased compiler trees into Java bytecode format.

[You can read more about phases here](../architecture/phases.md#phase-categories).

#### Drivers

The core compiler also requires a lot of state to be initialised before use, such as [settings][ScalaSettings]
and the [Context](../architecture/context.md). For convenience, the [Driver] class contains high level functions for
configuring the compiler and invoking it programatically. The object [Main] inherits from `Driver`
and is invoked by the `scalac` script.

## Code Structure

The code of the compiler is found in the package [dotty.tools],
containing the following sub-packages:
```scala
tools // contains helpers and the `scala` generic runner
├── backend // Compiler backends (currently JVM and JS)
├── dotc // The main compiler, with subpackages:
│ ├── ast // Abstract syntax trees
│   ├── classpath
│   ├── config // Compiler configuration, settings, platform specific definitions.
│   ├── core // Core data structures and operations, with specific subpackages for:
│   │   ├── classfile // Reading of Java classfiles into core data structures
│   │   ├── tasty // Reading and writing of TASTY files to/from core data structures
│   │   └── unpickleScala2 // Reading of Scala2 symbol information into core data structures
│   ├── decompiler // pretty printing TASTY as code
│   ├── fromtasty // driver for recompilation from TASTY
│   ├── interactive // presentation compiler and code completions
│   ├── parsing // Scanner and parser
│   ├── plugins // compile plugin definitions
│   ├── printing // Pretty-printing trees, types and other data
│   ├── profile // internals for profiling the compiler
│   ├── quoted // internals for quoted reflection
│   ├── reporting // Reporting of error messages, warnings and other info.
│   ├── rewrites // Helpers for rewriting Scala 2's constructs into Scala 3's.
│   ├── sbt // Helpers for communicating with the Zinc compiler.
│   ├── semanticdb // Helpers for exporting semanticdb from trees.
│   ├── transform // Miniphases and helpers for tree transformations.
│   ├── typer // Type-checking
│   └── util // General purpose utility classes and modules.
├── io // Helper modules for file access and classpath handling.
├── repl // REPL driver and interaction with the terminal
├── runner // helpers for the `scala` generic runner script
└── scripting // scala runner for the -script argument
```


[Phases]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Phases.scala
[CompilationUnit]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala

[dotty.tools]: https://github.com/lampepfl/dotty/tree/master/compiler/src/dotty/tools
[ScalaSettings]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
[syntax]: https://docs.scala-lang.org/scala3/reference/syntax.html
[Main]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Main.scala
[Driver]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Driver.scala
[Compiler]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Compiler.scala
[Run]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Run.scala
108 changes: 108 additions & 0 deletions docs/_docs/contributing/architecture/phases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
layout: doc-page
title: Compiler Phases
---

As described in the [compiler overview](lifecycle.md#phases), `dotc` is divided into a list of [phases][Phase],
specified in the [Compiler] class.

#### Printing the phases of the Compiler

a flattened list of all the phases can be displayed by invoking
the compiler with the `-Xshow-phases` flag:
```
$ scalac -Xshow-phases
```

## Phase Groups

In class [Compiler] you can access the list of phases with the method `phases`:

```scala
def phases: List[List[Phase]] =
frontendPhases ::: picklerPhases ::: transformPhases ::: backendPhases
```

You can see that phases are actually grouped into sublists, given by the signature
`List[List[Phase]]`; that is, each sublist forms a phase group that is then *fused* into a
single tree traversal when a [Run] is executed.

Phase fusion allows each phase of a group to be small and modular,
(each performing a single function), while reducing the number of tree traversals
and increasing performance.

Phases are able to be grouped together if they inherit from [MiniPhase].

## Phase Categories

Phases fall into four categories, allowing customisation by sub-classes of [Compiler]:

### `frontendPhases`
In the main compiler these include [parser], [typer], [posttyper],
[prepjsinterop] and phases for producing SemanticDB and communicating with the
incremental compiler Zinc.
The [parser] reads source programs and generates untyped abstract syntax trees, which
in [typer] are then typechecked and transformed into typed abstract syntax trees.
Following is [posttyper], performing checks and cleanups that require a fully typed program.
In particular, it
- creates super accessors representing `super` calls in traits
- creates implementations of compiler-implemented methods,
such as `equals` and `hashCode` for case classes.
- marks [compilation units][CompilationUnit] that require inline expansion, or quote pickling
- simplifies trees of erased definitions
- checks variance of type parameters
- mark parameters passed unchanged from subclass to superclass for later pruning.

### `picklerPhases`
These phases start with [pickler], which serializes typed trees
produced by the `frontendPhases` into TASTy format. Following is [inlining],
which expand calls to inline methods, and [postInlining] providing implementations
of the [Mirror] framework for inlined calls.
Finally are [staging], which ensures that quotes conform to the
[Phase Consistency Principle (PCP)][PCP], and [pickleQuotes] which converts quoted
trees to embedded TASTy strings.

### `transformPhases`
These phases are concerned with tranformation into lower-level forms
suitable for the runtime system, with two sub-groupings:
- High-level transformations: All phases from [firstTransform] to [erasure].
Most of these phases transform syntax trees, expanding high-level constructs
to more primitive ones.
- An important transform phase is [patternMatcher], which converts match
trees and patterns into lower level forms, as well as checking the
exhaustivity of sealed types, and unreachability of pattern cases.
- Some phases perform further checks on more primitive trees,
e.g. [refchecks] verifies that no abstract methods exist in concrete classes,
and [initChecker] checks that fields are not used before initialisation.
- The last phase in the group, [erasure] translates all
types into types supported directly by the JVM. To do this, it performs
another type checking pass, but using the rules of the JVM's type system
instead of Scala's.
- Low-level transformations: All phases from `ElimErasedValueType` to
`CollectSuperCalls`. These further transform trees until they are essentially a
structured version of Java bytecode.

### `backendPhases`
These map the transformed trees to Java classfiles or SJSIR files.

[CompilationUnit]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala
[Compiler]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Compiler.scala
[Phase]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Phases.scala
[MiniPhase]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala
[Run]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Run.scala
[parser]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/parsing/ParserPhase.scala
[typer]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/typer/TyperPhase.scala
[posttyper]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
[prepjsinterop]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/sjs/PrepJSInterop.scala
[pickler]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Pickler.scala
[inlining]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Inlining.scala
[postInlining]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PostInlining.scala
[staging]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Staging.scala
[pickleQuotes]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala
[refchecks]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/typer/RefChecks.scala
[initChecker]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/init/Checker.scala
[firstTransform]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
[patternMatcher]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
[erasure]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Erasure.scala
[Mirror]: https://github.com/lampepfl/dotty/blob/master/library/src/scala/deriving/Mirror.scala
[PCP]: {{ site.scala3ref }}/metaprogramming/macros.html#the-phase-consistency-principle
70 changes: 70 additions & 0 deletions docs/_docs/contributing/architecture/symbols.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
layout: doc-page
title: Symbols
---

As discussed previously, `dotc` [maintains time-indexed views](time.md) of various
compiler artifacts. The following sections discuss how they are managed in the compiler.

## Symbols

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.

## Definitions are Dynamic

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][Denotations]) to compute views of definitions across phases,
as many of attributes associated with definitions are phase-dependent. For example:
- types are gradually simplified by several phases,
- owners change in [lambdaLift] (local methods are lifted to an enclosing class)
and [flatten] (when inner classes are moved to the top level)
- Names are changed when private members need to be accessed from outside
their class (for instance from a nested class or a class implementing
a trait).

Additionally, symbols are not suitable to be used as a reference to
a definition in another [compilation unit][CompilationUnit].
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.

## Denotations

On its own a `Symbol` has no structure. Its semantic meaning is given by being associated
with a [Denotation][Denotations].

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`.

### SymDenotations
All definition symbols will contain a `SymDenotation`. The denotation, in turn, contains:
- a reverse link to the source symbol
- a reference to the enclosing symbol that defined the source symbol:
- for a local variable, the enclosing method
- for a field or class, the enclosing class
- a set of [flags], describing the definition (e.g. whether it's a trait or mutable).
- the type of the definition (through the `info` method)
- a [signature][Signature1], which uniquely identifies overloaded methods (or else `NotAMethod`).
- and more.

A class symbol will instead be associated with a `ClassDenotation`, which extends `SymDenotation`
with some additional fields specific for classes.

[Signature1]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Signature.scala#L9-L33
[Symbols]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Symbols.scala
[flatten]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Flatten.scala
[lambdaLift]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala
[CompilationUnit]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala
[Denotations]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Denotations.scala
[SymDenotations]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
[flags]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Flags.scala
Loading