Edit this page on GitHub


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
... and so on