docs/_docs/internals/contexts.md
The Context contains the state of the compiler, for example
settingsfreshNames (FreshNameCreator)period (run and phase id)compilationUnitphasetree (current tree)typer (current typer)mode (type checking mode)typerState (for example undetermined type variables)The type checker passes contexts through all methods and adapts fields where necessary, e.g.
case tree: untpd.Block => typedBlock(desugar.block(tree), pt)(ctx.fresh.withNewScope)
A number of fields in the context are typer-specific (mode, typerState).
Other phases need a context for many things, for example to access the denotation of a symbols (depends on the period). However they typically don't need to modify / extend the context while traversing the AST. For these phases the context can be simply an implicit class parameter that is then available in all members.
Careful: beware of memory leaks. Don't hold on to contexts in long lived objects.
Nested contexts should be named ctx to enable implicit shadowing:
scala> class A
scala> def foo(implicit a: A) { def bar(implicit b: A) { println(implicitly[A]) } }
<console>:8: error: ambiguous implicit values:
both value a of type A
and value b of type A
match expected type A
def foo(implicit a: A) { def bar(implicit b: A) { println(implicitly[A]) } }
scala> def foo(implicit a: A) { def bar(implicit a: A) { println(implicitly[A]) } }
foo: (implicit a: A)Unit