Skip to content

Commit ae66277

Browse files
committed
Redo scheme for typing late-loaded units
We got into problems when the symbols were entered in one run and the tree was demanded in a subsequent run. In that case we'd need to time-travel back which the framework does not really support. The new scheme makes sure the typechecking is done at the same run as when the symbols were entered. It either immediately typechecks them, or if called during a compile, waits until the end of the compile. The latter twist is done so that we do not cause new cycles.
1 parent 7c0e5e9 commit ae66277

File tree

2 files changed

+23
-26
lines changed

2 files changed

+23
-26
lines changed

compiler/src/dotty/tools/dotc/Run.scala

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
6161
(start.setRun(this) /: defn.RootImportFns)(addImport)
6262
}
6363

64+
private[this] var compiling = false
65+
6466
private[this] var myCtx = rootContext(ictx)
6567

6668
/** The context created for this run */
@@ -96,6 +98,9 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
9698
/** The source files of all late entered symbols, as a set */
9799
private[this] var lateFiles = mutable.Set[AbstractFile]()
98100

101+
/** Actions that need to be performed at the end of the current compilation run */
102+
private[this] var finalizeActions = mutable.ListBuffer[() => Unit]()
103+
99104
def getSource(fileName: String): SourceFile = {
100105
val f = new PlainFile(io.Path(fileName))
101106
if (f.isDirectory) {
@@ -143,6 +148,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
143148

144149
protected def compileUnits()(implicit ctx: Context) = Stats.maybeMonitored {
145150
ctx.checkSingleThreaded()
151+
compiling = true
146152

147153
// If testing pickler, make sure to stop after pickling phase:
148154
val stopAfter =
@@ -184,31 +190,32 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
184190
ctx.phases.foreach(_.initContext(runCtx))
185191
runPhases(runCtx)
186192
if (!ctx.reporter.hasErrors) Rewrites.writeBack()
193+
while (finalizeActions.nonEmpty) {
194+
val action = finalizeActions.remove(0)
195+
action()
196+
}
197+
compiling = false
187198
}
188199

189200
/** Enter top-level definitions of classes and objects contain in Scala source file `file`.
190201
* The newly added symbols replace any previously entered symbols.
202+
* If `typeCheck = true`, also run typer on the compilation unit.
191203
*/
192-
def enterRoots(file: AbstractFile)(implicit ctx: Context): Option[CompilationUnit] =
204+
def lateCompile(file: AbstractFile, typeCheck: Boolean)(implicit ctx: Context): Unit =
193205
if (!files.contains(file) && !lateFiles.contains(file)) {
194206
lateFiles += file
195207
val unit = new CompilationUnit(getSource(file.path))
196-
enterRoots(unit)(runContext.fresh.setCompilationUnit(unit))
197-
Some(unit)
208+
def process()(implicit ctx: Context) = {
209+
unit.untpdTree = new Parser(unit.source).parse()
210+
ctx.typer.lateEnter(unit.untpdTree)
211+
def typeCheckUnit() = unit.tpdTree = ctx.typer.typedExpr(unit.untpdTree)
212+
if (typeCheck)
213+
if (compiling) finalizeActions += (() => typeCheckUnit()) else typeCheckUnit()
214+
}
215+
process()(runContext.fresh.setCompilationUnit(unit))
198216
}
199217
else None
200218

201-
private def enterRoots(unit: CompilationUnit)(implicit ctx: Context): Unit = {
202-
unit.untpdTree = new Parser(unit.source).parse()
203-
ctx.typer.lateEnter(unit.untpdTree)
204-
}
205-
206-
def typedTree(unit: CompilationUnit)(implicit ctx: Context) = {
207-
def typeCheck(implicit ctx: Context) = ctx.typer.typedExpr(unit.untpdTree)
208-
if (unit.tpdTree.isEmpty) unit.tpdTree = typeCheck(runContext.fresh.setCompilationUnit(unit))
209-
unit.tpdTree
210-
}
211-
212219
private sealed trait PrintedTree
213220
private /*final*/ case class SomePrintedTree(phase: String, tree: String) extends PrintedTree
214221
private object NoPrintedTree extends PrintedTree

compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -397,16 +397,6 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
397397
class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader {
398398
def description(implicit ctx: Context) = "source file " + srcfile.toString
399399
override def sourceFileOrNull = srcfile
400-
def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = {
401-
for (unit <- ctx.run.enterRoots(srcfile))
402-
if (ctx.settings.YretainTrees.value) {
403-
val (classRoot, moduleRoot) = rootDenots(root.asClass)
404-
val treeProvider = new tpd.TreeProvider {
405-
def computeTrees(implicit ctx: Context): List[tpd.Tree] =
406-
ctx.run.typedTree(unit) :: Nil
407-
}
408-
classRoot.classSymbol.treeOrProvider = treeProvider
409-
moduleRoot.classSymbol.treeOrProvider = treeProvider
410-
}
411-
}
400+
def doComplete(root: SymDenotation)(implicit ctx: Context): Unit =
401+
ctx.run.lateCompile(srcfile, typeCheck = ctx.settings.YretainTrees.value)
412402
}

0 commit comments

Comments
 (0)