Skip to content

Commit 40ba19a

Browse files
committed
Move Staging before Pickler
1 parent ebe73b3 commit 40ba19a

File tree

6 files changed

+82
-29
lines changed

6 files changed

+82
-29
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ class Compiler {
4545

4646
/** Phases dealing with TASTY tree pickling and unpickling */
4747
protected def picklerPhases: List[List[Phase]] =
48-
List(new Pickler) :: // Generate TASTY info
4948
List(new Staging) :: // Check quotation levels (while healing types) and expand macros
49+
List(new Pickler) :: // Generate TASTY info
5050
List(new ReifyQuotes) :: // Turn quoted trees into explicit run-time data structures
5151
Nil
5252

compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ class TreeTypeMap(
162162
assert(!to.exists(substFrom contains _))
163163
assert(!from.exists(newOwners contains _))
164164
assert(!to.exists(oldOwners contains _))
165-
new TreeTypeMap(
165+
newTreeTypeMap(
166166
typeMap,
167167
treeMap,
168168
from ++ oldOwners,
@@ -171,6 +171,11 @@ class TreeTypeMap(
171171
to ++ substTo)
172172
}
173173

174+
protected def newTreeTypeMap(typeMap: Type => Type, treeMap: tpd.Tree => tpd.Tree,
175+
oldOwners: List[Symbol], newOwners: List[Symbol], substFrom: List[Symbol], substTo: List[Symbol]) = {
176+
new TreeTypeMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo)
177+
}
178+
174179
/** Apply `typeMap` and `ownerMap` to given symbols `syms`
175180
* and return a treemap that contains the substitution
176181
* between original and mapped symbols.

compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers
775775
tpd.Return(expr, ctx.owner)
776776

777777
def copy(original: Tree)(expr: Term)(implicit ctx: Context): Return =
778-
tpd.cpy.Return(original)(expr, tpd.EmptyTree)
778+
tpd.cpy.Return(original)(expr, tpd.ref(ctx.owner))
779779

780780
def unapply(x: Term)(implicit ctx: Context): Option[Term] = x match {
781781
case x: tpd.Return => Some(x.expr)

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

Lines changed: 71 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
1-
package dotty.tools.dotc
2-
package transform
3-
4-
import core._
5-
import Decorators._, Flags._, Types._, Contexts._, Symbols._, Constants._
6-
import ast.Trees._
7-
import ast.{TreeTypeMap, untpd}
8-
import util.Positions._
9-
import tasty.TreePickler.Hole
10-
import SymUtils._
11-
import NameKinds._
12-
import dotty.tools.dotc.ast.tpd
13-
import typer.Implicits.SearchFailureType
1+
package dotty.tools.dotc.transform
2+
3+
import dotty.tools.dotc.ast.Trees._
4+
import dotty.tools.dotc.ast.{TreeTypeMap, tpd, untpd}
5+
import dotty.tools.dotc.core.Constants._
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.NameKinds._
10+
import dotty.tools.dotc.core.Symbols._
11+
import dotty.tools.dotc.core.Types._
12+
import dotty.tools.dotc.core.tasty.TreePickler.Hole
13+
import dotty.tools.dotc.reporting
14+
import dotty.tools.dotc.transform.SymUtils._
15+
import dotty.tools.dotc.typer.Implicits.SearchFailureType
16+
import dotty.tools.dotc.util.Positions._
17+
import dotty.tools.dotc.util.SourcePosition
1418

1519
import scala.collection.mutable
1620
import dotty.tools.dotc.core.StdNames._
1721
import dotty.tools.dotc.core.quoted._
18-
import dotty.tools.dotc.util.SourcePosition
1922

2023

2124
/** Checks that the phase consistency principle (PCP) holds, heals types and expand macros.
@@ -83,7 +86,7 @@ class Staging extends MacroTransformWithImplicits {
8386
* These will be turned into splices using `addTags` and represent types spliced
8487
* explicitly.
8588
*/
86-
val explicitTags = new mutable.LinkedHashSet[TypeRef]()
89+
val explicitTags = new mutable.LinkedHashSet[(TypeRef, Position)]()
8790

8891
/** A stack of entered symbols, to be unwound after scope exit */
8992
var enteredSyms: List[Symbol] = Nil
@@ -111,7 +114,8 @@ class Staging extends MacroTransformWithImplicits {
111114
name = UniqueName.fresh("T".toTermName).toTypeName,
112115
flags = Synthetic,
113116
info = TypeAlias(tag.tpe.select(tpnme.UNARY_~)),
114-
coord = typeRef.prefix.termSymbol.coord).asType
117+
coord = alias.pos
118+
).asType
115119

116120
ctx.typeAssigner.assignType(untpd.TypeDef(local.name, alias), local)
117121
}
@@ -126,11 +130,11 @@ class Staging extends MacroTransformWithImplicits {
126130
importedTags.clear()
127131

128132
// The tree of the tag for each tag comes from a type ref e.g., ~t
129-
val explicitTypeDefs = for (tref <- explicitTags) yield {
130-
val tag = ref(tref.prefix.termSymbol)
133+
val explicitTypeDefs = for ((tref, pos) <- explicitTags) yield {
134+
val tag = ref(tref.prefix.termSymbol).withPos(pos)
131135
mkTagSymbolAndAssignType(tref, tag)
132136
}
133-
val tagsExplicitTypeDefsPairs = explicitTags.zip(explicitTypeDefs)
137+
val tagsExplicitTypeDefsPairs = explicitTags.map(_._1).zip(explicitTypeDefs)
134138
explicitTags.clear()
135139

136140
// Maps type splices to type references of tags e.g., ~t -> some type T$1
@@ -150,8 +154,52 @@ class Staging extends MacroTransformWithImplicits {
150154
}
151155
}
152156

157+
/** Type tree map that does not tag type at level 0 */
158+
class QuoteTreeTypeMap(
159+
typeMap: Type => Type = IdentityTypeMap,
160+
treeMap: tpd.Tree => tpd.Tree = identity _,
161+
oldOwners: List[Symbol] = Nil,
162+
newOwners: List[Symbol] = Nil,
163+
substFrom: List[Symbol] = Nil,
164+
substTo: List[Symbol] = Nil
165+
)(implicit ctx: Context) extends TreeTypeMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo) { self =>
166+
167+
protected var level = 1 // TODO use context to keep track of the level
168+
169+
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = {
170+
if (level == 0) {
171+
// Keep transforming but do not replace insert the taged types. Types in nested quotes are also not taged.
172+
val (sFrom, sTo) = substFrom.zip(substTo).filterNot(_._2.is(Synthetic)).unzip // TODO Syntetic is probably not enugh to distinguish added types
173+
new TreeTypeMap(typeMap, treeMap,
174+
oldOwners, newOwners,
175+
sFrom, sTo
176+
).transform(tree)
177+
}
178+
else if (tree.symbol.isSplice) {
179+
level -= 1
180+
try super.transform(tree)
181+
finally level += 1
182+
} else if (tree.symbol.isQuote) {
183+
level += 1
184+
try super.transform(tree)
185+
finally level -= 1
186+
}
187+
else super.transform(tree)
188+
189+
}
190+
191+
protected override def newTreeTypeMap(typeMap: Type => Type, treeMap: tpd.Tree => tpd.Tree,
192+
oldOwners: List[Symbol], newOwners: List[Symbol],
193+
substFrom: List[Symbol], substTo: List[Symbol]) = {
194+
new QuoteTreeTypeMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo) {
195+
level = self.level
196+
}
197+
}
198+
199+
}
200+
153201
Block(typeDefs ++ explicitTypeDefs,
154-
new TreeTypeMap(
202+
new QuoteTreeTypeMap(
155203
treeMap = trMap,
156204
typeMap = tpMap,
157205
substFrom = itags.map(_._1.symbol),
@@ -243,7 +291,7 @@ class Staging extends MacroTransformWithImplicits {
243291
tp match {
244292
case tp: TypeRef if tp.symbol.isSplice =>
245293
if (inQuote) {
246-
explicitTags += tp
294+
explicitTags += Tuple2(tp, pos)
247295
outer.checkType(pos).foldOver(acc, tp)
248296
}
249297
else {
@@ -333,7 +381,7 @@ class Staging extends MacroTransformWithImplicits {
333381
}
334382
else if (enclosingInlineds.nonEmpty) { // level 0 in an inlined call
335383
val spliceCtx = ctx.outer // drop the last `inlineContext`
336-
val pos: SourcePosition = Decorators.sourcePos(enclosingInlineds.head.pos)(spliceCtx)
384+
val pos: SourcePosition = sourcePos(enclosingInlineds.head.pos)(spliceCtx)
337385
val evaluatedSplice = Splicer.splice(splice.qualifier, pos, macroClassLoader)(spliceCtx).withPos(splice.pos)
338386
if (ctx.reporter.hasErrors) splice else transform(evaluatedSplice)
339387
}
@@ -396,7 +444,7 @@ class Staging extends MacroTransformWithImplicits {
396444
tree.rhs match {
397445
case InlineSplice(_) =>
398446
mapOverTree(enteredSyms) // Ignore output, only check PCP
399-
cpy.DefDef(tree)(rhs = defaultValue(tree.rhs.tpe))
447+
tree
400448
case _ =>
401449
ctx.error(
402450
"""Malformed macro.

library/src/scala/tasty/reflect/TreeOps.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ trait TreeOps extends Core {
637637

638638
/** Scala local `return` */
639639
val Return: ReturnModule
640-
abstract class ReturnModule {
640+
abstract class ReturnModule { // TODO should we expose explicitly the returns `from`?
641641

642642
/** Creates `return <expr: Term>` */
643643
def apply(expr: Term)(implicit ctx: Context): Return

tests/plugins/neg/divideZero/plugin_1.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import transform.MegaPhase.MiniPhase
88
import Decorators._
99
import Symbols.Symbol
1010
import Constants.Constant
11-
import transform.{Pickler, Staging}
11+
import transform.{Pickler, ReifyQuotes}
1212
import StdNames._
1313

1414
class DivideZero extends PluginPhase with StandardPlugin {
@@ -18,7 +18,7 @@ class DivideZero extends PluginPhase with StandardPlugin {
1818
val phaseName = name
1919

2020
override val runsAfter = Set(Pickler.name)
21-
override val runsBefore = Set(Staging.name)
21+
override val runsBefore = Set(ReifyQuotes.name)
2222

2323
override def init(options: List[String]): List[PluginPhase] = this :: Nil
2424

0 commit comments

Comments
 (0)