@@ -16,6 +16,25 @@ import config.{Settings, Platform, JavaPlatform}
16
16
17
17
object Contexts {
18
18
19
+ /** A context is passed basically everywhere in dotc.
20
+ * This is convenient but carries the risk of captured contexts in
21
+ * objects that turn into space leaks. To combat this risk, here are some
22
+ * conventions to follow:
23
+ *
24
+ * - Never let an implicit context be an argument of a class whose instances
25
+ * live longer than the context.
26
+ * - Classes that need contexts for their initialization take an explicit parameter
27
+ * named `initctx`. They pass initctx to all positions where it is needed
28
+ * (and these positions should all be part of the intialization sequence of the class).
29
+ * - Classes that need contexts that survive initialization are passed
30
+ * a "condensed context", typically named `cctx` instead. Consensed contexts
31
+ * just add some basic information to the context base without the
32
+ * risk of capturing complete trees.
33
+ * - To make sure these rules are kept, it would be good to do a sanity
34
+ * check using bytecode inspection with javap or scalap: Keep track
35
+ * of all class fields of type context; allow them only in whitelisted
36
+ * classes (which should be short-lived).
37
+ */
19
38
abstract class Context extends Periods
20
39
with Substituters
21
40
with TypeOps
@@ -182,6 +201,10 @@ object Contexts {
182
201
private [core] val pendingVolatiles = new mutable.HashSet [Type ]
183
202
}
184
203
204
+ object Context {
205
+ implicit def toPrinter (ctx : Context ) = ctx.printer(ctx)
206
+ }
207
+
185
208
implicit def ctxToBase (ctx : Context ): ContextBase = ctx.base
186
209
187
210
/** Initial size of superId table */
0 commit comments