Skip to content

Commit 2f4d8f6

Browse files
committed
Put position check into a phase
1 parent a52c208 commit 2f4d8f6

File tree

3 files changed

+65
-38
lines changed

3 files changed

+65
-38
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class Compiler {
3737
/** Phases dealing with the frontend up to trees ready for TASTY pickling */
3838
protected def frontendPhases: List[List[Phase]] =
3939
List(new FrontEnd) :: // Compiler frontend: scanner, parser, namer, typer
40+
List(new YCheckPositions) :: // YCheck positions
4041
List(new Staging) :: // Check PCP, heal quoted types and expand macros
4142
List(new sbt.ExtractDependencies) :: // Sends information on classes' dependencies to sbt via callbacks
4243
List(new PostTyper) :: // Additional checks and cleanups after type checking

compiler/src/dotty/tools/dotc/transform/Staging.scala

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -64,44 +64,6 @@ class Staging extends MacroTransform {
6464
case _ =>
6565
}
6666
}
67-
if (ctx.phase <= ctx.erasurePhase) {
68-
tree match {
69-
case PackageDef(pid, _) if tree.symbol.owner == defn.RootClass =>
70-
new TreeTraverser {
71-
private[this] var sources: List[SourceFile] = ctx.source :: Nil
72-
def traverse(tree: tpd.Tree)(implicit ctx: Context): Unit = {
73-
assert(ctx.source == sources.head)
74-
if (!tree.isEmpty && !tree.isInstanceOf[untpd.TypedSplice] && ctx.typerState.isGlobalCommittable) {
75-
if (!tree.isType) { // TODO also check types, currently we do not add Inlined(EmptyTree, _, _) for types. We should.
76-
val currentSource = sources.head
77-
assert(tree.source == currentSource, i"wrong source set for $tree # ${tree.uniqueId} of ${tree.getClass}, set to ${tree.source} but context had $currentSource")
78-
}
79-
}
80-
tree match {
81-
case Inlined(EmptyTree, bindings, expansion) =>
82-
assert(bindings.isEmpty)
83-
val old = sources
84-
sources = old.tail
85-
traverse(expansion)(inlineContext(EmptyTree))
86-
sources = old
87-
case Inlined(call, bindings, expansion) =>
88-
bindings.foreach(traverse(_))
89-
sources = call.symbol.topLevelClass.source :: sources
90-
if (
91-
!( // FIXME macro implementations can drop Inlined nodes. We should reinsert them after macro expansion based on the positions of the trees
92-
((ctx.phase <= ctx.typerPhase.next) && call.symbol.is(Macro)) ||
93-
(!(ctx.phase <= ctx.typerPhase.next) && call.symbol.unforcedDecls.exists(_.is(Macro)) || call.symbol.unforcedDecls.toList.exists(_.is(Macro)))
94-
)
95-
) traverse(expansion)(inlineContext(call))
96-
sources = sources.tail
97-
case _ => traverseChildren(tree)
98-
}
99-
}
100-
}.traverse(tree)
101-
case _ =>
102-
}
103-
104-
}
10567
}
10668

10769
override def run(implicit ctx: Context): Unit =
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import dotty.tools.dotc.ast.Trees._
5+
import dotty.tools.dotc.ast.{tpd, untpd}
6+
import dotty.tools.dotc.core.Contexts._
7+
import dotty.tools.dotc.core.Decorators._
8+
import dotty.tools.dotc.core.Flags._
9+
import dotty.tools.dotc.core.Phases
10+
import dotty.tools.dotc.core.Symbols._
11+
import dotty.tools.dotc.util.{SourceFile, SourcePosition}
12+
13+
/** Ycheck inlined positions */
14+
class YCheckPositions extends Phases.Phase {
15+
import tpd._
16+
17+
def phaseName: String = "inlinedPositions"
18+
19+
override def run(implicit ctx: Context): Unit = () // YCheck only
20+
21+
override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = {
22+
tree match {
23+
case PackageDef(pid, _) if tree.symbol.owner == defn.RootClass =>
24+
new TreeTraverser {
25+
private[this] var sources: List[SourceFile] = ctx.source :: Nil
26+
def traverse(tree: tpd.Tree)(implicit ctx: Context): Unit = {
27+
28+
// Check current context is correct
29+
assert(ctx.source == sources.head)
30+
if (!tree.isEmpty && !tree.isInstanceOf[untpd.TypedSplice] && ctx.typerState.isGlobalCommittable) {
31+
if (!tree.isType) { // TODO also check types, currently we do not add Inlined(EmptyTree, _, _) for types. We should.
32+
val currentSource = sources.head
33+
assert(tree.source == currentSource, i"wrong source set for $tree # ${tree.uniqueId} of ${tree.getClass}, set to ${tree.source} but context had $currentSource")
34+
}
35+
}
36+
37+
// Recursivlely check children while keeping track of current source
38+
tree match {
39+
case Inlined(EmptyTree, bindings, expansion) =>
40+
assert(bindings.isEmpty)
41+
val old = sources
42+
sources = old.tail
43+
traverse(expansion)(inlineContext(EmptyTree))
44+
sources = old
45+
case Inlined(call, bindings, expansion) =>
46+
bindings.foreach(traverse(_))
47+
sources = call.symbol.topLevelClass.source :: sources
48+
if (
49+
!( // FIXME macro implementations can drop Inlined nodes. We should reinsert them after macro expansion based on the positions of the trees
50+
((ctx.phase <= ctx.typerPhase.next) && call.symbol.is(Macro)) ||
51+
(!(ctx.phase <= ctx.typerPhase.next) && call.symbol.unforcedDecls.exists(_.is(Macro)) || call.symbol.unforcedDecls.toList.exists(_.is(Macro)))
52+
)
53+
) traverse(expansion)(inlineContext(call))
54+
sources = sources.tail
55+
case _ => traverseChildren(tree)
56+
}
57+
}
58+
}.traverse(tree)
59+
case _ =>
60+
}
61+
62+
}
63+
64+
}

0 commit comments

Comments
 (0)