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 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:
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 |