docs/_docs/contributing/architecture/context.md
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`
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 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 |