Skip to content

Commit 1a995eb

Browse files
committed
Change reify for types
We now keep the (type-) trees and proceed as with normal reification. This saves us the trouble of having to define a separate pickler for types with splices in them.
1 parent 9b6e03a commit 1a995eb

File tree

4 files changed

+46
-41
lines changed

4 files changed

+46
-41
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,7 @@ object Mode {
9393

9494
/** We are in the IDE */
9595
val Interactive = newMode(20, "Interactive")
96+
97+
/** We are in a quoted type during the ReifyQuotes phase */
98+
val InQuotedType = newMode(21, "InQuotedType")
9699
}

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,19 +188,20 @@ class FirstTransform extends MiniPhase with InfoTransformer { thisPhase =>
188188
override def transformStats(trees: List[Tree])(implicit ctx: Context): List[Tree] =
189189
ast.Trees.flatten(reorderAndComplete(trees)(ctx.withPhase(thisPhase.next)))
190190

191+
private def toTypeTree(tree: Tree)(implicit ctx: Context) =
192+
if (ctx.mode.is(Mode.InQuotedType)) tree else TypeTree(tree.tpe).withPos(tree.pos)
193+
191194
override def transformOther(tree: Tree)(implicit ctx: Context) = tree match {
192195
case tree: Import => EmptyTree
193196
case tree: NamedArg => transformAllDeep(tree.arg)
194-
case tree => if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos) else tree
197+
case tree => if (tree.isType) toTypeTree(tree) else tree
195198
}
196199

197200
override def transformIdent(tree: Ident)(implicit ctx: Context) =
198-
if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
199-
else constToLiteral(tree)
201+
if (tree.isType) toTypeTree(tree) else constToLiteral(tree)
200202

201203
override def transformSelect(tree: Select)(implicit ctx: Context) =
202-
if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
203-
else constToLiteral(tree)
204+
if (tree.isType) toTypeTree(tree) else constToLiteral(tree)
204205

205206
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context) =
206207
constToLiteral(tree)

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

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,59 +9,60 @@ import MegaPhase.MiniPhase
99
import scala.collection.mutable
1010

1111
/** Translates quoted terms and types to reify method calls.
12+
* The mini phase needs to run in the same group as FirstTransform. So far we lack
13+
* the machinery to express this constraint in code.
1214
*/
1315
class ReifyQuotes extends MiniPhase {
1416
import ast.tpd._
1517

1618
override def phaseName: String = "reifyQuotes"
1719

18-
def reifyTree(tree: Tree)(implicit ctx: Context): String = i"($tree)" // TODO: replace with TASTY
19-
def reifyType(tpe: Type)(implicit ctx: Context): String = i"[$tpe]" // TODO: replace with TASTY
20+
/** Serialize `tree`. Embedded splices are represented as nodes of the form
21+
*
22+
* Select(qual, sym)
23+
*
24+
* where `sym` is either `defn.MetaExpr_~` or `defn.MetaType_~`. For any splice,
25+
* the `qual` part will be of the form `Typed(EmptyTree, TypeTree(<underlying type>))`,
26+
* but that knowledge is not needed to uniquely identify a splice node.
27+
*/
28+
def reifyTree(tree: Tree)(implicit ctx: Context): String = tree.show // TODO: replace with TASTY
2029

21-
private def reifyCall(meth: Symbol, typeArg: Type, reified: String, splices: List[Tree])(implicit ctx: Context) =
22-
ref(meth)
23-
.appliedToType(typeArg)
24-
.appliedTo(
25-
Literal(Constant(reified)),
26-
SeqLiteral(splices, TypeTree(defn.MetaExprType.appliedTo(TypeBounds.empty))))
30+
private def reifyCall(body: Tree, isType: Boolean)(implicit ctx: Context) = {
2731

28-
override def transformApply(tree: Apply)(implicit ctx: Context): Tree = {
2932
object liftSplices extends TreeMap {
3033
val splices = new mutable.ListBuffer[Tree]
3134
override def transform(tree: Tree)(implicit ctx: Context) = tree match {
32-
case tree @ Select(qual, name) if tree.symbol == defn.MetaExpr_~ =>
35+
case tree @ Select(qual, name)
36+
if tree.symbol == defn.MetaExpr_~ || tree.symbol == defn.MetaType_~ =>
3337
splices += qual
3438
val placeHolder = Typed(EmptyTree, TypeTree(qual.tpe.widen))
3539
cpy.Select(tree)(placeHolder, name)
3640
case _ =>
3741
super.transform(tree)
3842
}
3943
}
40-
if (tree.fun.symbol == defn.quoteMethod) {
41-
val body = tree.args.head
42-
val reified = reifyTree(liftSplices.transform(body))
43-
reifyCall(defn.Reifier_reifyExpr, body.tpe.widen, reified, liftSplices.splices.toList)
44-
}
45-
else tree
44+
45+
val reified = reifyTree(liftSplices.transform(body))
46+
var splices = liftSplices.splices.toList
47+
if (isType) // transform splices again because embedded type trees were not rewritten before
48+
splices = splices.map(transformAllDeep(_)(ctx.retractMode(Mode.InQuotedType)))
49+
val spliceType = if (isType) defn.MetaTypeType else defn.MetaExprType
50+
51+
ref(if (isType) defn.Reifier_reifyType else defn.Reifier_reifyExpr)
52+
.appliedToType(if (isType) body.tpe else body.tpe.widen)
53+
.appliedTo(
54+
Literal(Constant(reified)),
55+
SeqLiteral(splices, TypeTree(spliceType.appliedTo(TypeBounds.empty))))
4656
}
4757

48-
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context): Tree = {
49-
object liftSplices extends TypeMap {
50-
val splices = new mutable.ListBuffer[Tree]
51-
override def apply(t: Type) = t match {
52-
case t @ TypeRef(pre: TermRef, _) if t.symbol == defn.MetaType_~ =>
53-
splices += ref(pre).withPos(tree.args.head.pos)
54-
val placeHolder = SkolemType(pre.widen)
55-
t.withPrefix(placeHolder)
56-
case _ =>
57-
mapOver(t)
58-
}
59-
}
60-
if (tree.fun.symbol == defn.typeQuoteMethod) {
61-
val body = tree.args.head.tpe
62-
val reified = reifyType(liftSplices(body))
63-
reifyCall(defn.Reifier_reifyType, body, reified, liftSplices.splices.toList)
64-
}
58+
override def transformApply(tree: Apply)(implicit ctx: Context): Tree =
59+
if (tree.fun.symbol == defn.quoteMethod) reifyCall(tree.args.head, isType = false)
6560
else tree
66-
}
67-
}
61+
62+
override def prepareForTypeApply(tree: TypeApply)(implicit ctx: Context): Context =
63+
if (tree.symbol == defn.typeQuoteMethod) ctx.addMode(Mode.InQuotedType) else ctx
64+
65+
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context): Tree =
66+
if (tree.fun.symbol == defn.typeQuoteMethod) reifyCall(tree.args.head, isType = true)
67+
else tree
68+
}

library/src/scala/meta/Reifier.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ object Reifier {
44

55
def reifyExpr[T](repr: String, args: Seq[Expr[_]]): Expr[T] = ???
66

7-
def reifyType[T](repr: String, args: Seq[Expr[_]]): Type[T] = ???
7+
def reifyType[T](repr: String, args: Seq[Type[_]]): Type[T] = ???
88

99
}

0 commit comments

Comments
 (0)