Contexts

The Context contains the state of the compiler, for example

Contexts in the typer

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

In other phases

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.

Using contexts

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