Skip to content

Commit b7ca9b1

Browse files
committed
Split transformQuotation into transformQuotedExpr and transformQuotedType
1 parent 938d3ae commit b7ca9b1

File tree

2 files changed

+46
-41
lines changed

2 files changed

+46
-41
lines changed

compiler/src/dotty/tools/dotc/staging/CrossStageSafety.scala

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -98,46 +98,47 @@ class CrossStageSafety extends TreeMapWithStages {
9898
}
9999

100100
/** Transform quoted trees while maintaining level correctness */
101-
override protected def transformQuotation(body: Tree, quote: Apply)(using Context): Tree = {
102-
val taggedTypes = new QuoteTypeTags(quote.span)
103-
101+
override protected def transformQuotedExpr(body: Tree, quote: Apply)(using Context): Tree = {
104102
if (ctx.property(InAnnotation).isDefined)
105103
report.error("Cannot have a quote in an annotation", quote.srcPos)
106104

107105
val stripAnnotsDeep: TypeMap = new TypeMap:
108106
def apply(tp: Type): Type = mapOver(tp.stripAnnots)
107+
val transformedBody = transformQuoteBody(body, quote)
108+
// `quoted.runtime.Expr.quote[T](<body>)` --> `quoted.runtime.Expr.quote[T2](<body2>)`
109+
val TypeApply(fun, targs) = quote.fun: @unchecked
110+
val targs2 = targs.map(targ => TypeTree(healType(quote.fun.srcPos)(stripAnnotsDeep(targ.tpe))))
111+
cpy.Apply(quote)(cpy.TypeApply(quote.fun)(fun, targs2), transformedBody :: Nil)
112+
}
109113

110-
def transformBody() =
111-
val contextWithQuote =
112-
if level == 0 then contextWithQuoteTypeTags(taggedTypes)(using quoteContext)
113-
else quoteContext
114-
val transformedBody = transform(body)(using contextWithQuote)
115-
taggedTypes.getTypeTags match
116-
case Nil => transformedBody
117-
case tags => tpd.Block(tags, transformedBody).withSpan(body.span)
118-
119-
if body.isTerm then
120-
val transformedBody = transformBody()
121-
// `quoted.runtime.Expr.quote[T](<body>)` --> `quoted.runtime.Expr.quote[T2](<body2>)`
122-
val TypeApply(fun, targs) = quote.fun: @unchecked
123-
val targs2 = targs.map(targ => TypeTree(healType(quote.fun.srcPos)(stripAnnotsDeep(targ.tpe))))
124-
cpy.Apply(quote)(cpy.TypeApply(quote.fun)(fun, targs2), transformedBody :: Nil)
125-
else
126-
body.tpe match
127-
case DirectTypeOf(termRef) =>
128-
// Optimization: `quoted.Type.of[x.Underlying](quotes)` --> `x`
129-
ref(termRef).withSpan(quote.span)
130-
case _ =>
131-
transformBody() match
132-
case DirectTypeOf.Healed(termRef) =>
133-
// Optimization: `quoted.Type.of[@SplicedType type T = x.Underlying; T](quotes)` --> `x`
134-
ref(termRef).withSpan(quote.span)
135-
case transformedBody =>
136-
val quotes = quote.args.mapConserve(transform)
137-
// `quoted.Type.of[<body>](quotes)` --> `quoted.Type.of[<body2>](quotes)`
138-
val TypeApply(fun, _) = quote.fun: @unchecked
139-
cpy.Apply(quote)(cpy.TypeApply(quote.fun)(fun, transformedBody :: Nil), quotes)
114+
override protected def transformQuotedType(body: Tree, quote: Apply)(using Context): Tree = {
115+
if (ctx.property(InAnnotation).isDefined)
116+
report.error("Cannot have a quote in an annotation", quote.srcPos)
117+
body.tpe match
118+
case DirectTypeOf(termRef) =>
119+
// Optimization: `quoted.Type.of[x.Underlying](quotes)` --> `x`
120+
ref(termRef).withSpan(quote.span)
121+
case _ =>
122+
transformQuoteBody(body, quote) match
123+
case DirectTypeOf.Healed(termRef) =>
124+
// Optimization: `quoted.Type.of[@SplicedType type T = x.Underlying; T](quotes)` --> `x`
125+
ref(termRef).withSpan(quote.span)
126+
case transformedBody =>
127+
val quotes = quote.args.mapConserve(transform)
128+
// `quoted.Type.of[<body>](quotes)` --> `quoted.Type.of[<body2>](quotes)`
129+
val TypeApply(fun, _) = quote.fun: @unchecked
130+
cpy.Apply(quote)(cpy.TypeApply(quote.fun)(fun, transformedBody :: Nil), quotes)
131+
}
140132

133+
private def transformQuoteBody(body: Tree, quote: Apply)(using Context): Tree = {
134+
val taggedTypes = new QuoteTypeTags(quote.span)
135+
val contextWithQuote =
136+
if level == 0 then contextWithQuoteTypeTags(taggedTypes)(using quoteContext)
137+
else quoteContext
138+
val transformedBody = transform(body)(using contextWithQuote)
139+
taggedTypes.getTypeTags match
140+
case Nil => transformedBody
141+
case tags => tpd.Block(tags, transformedBody).withSpan(body.span)
141142
}
142143

143144
/** Transform splice

compiler/src/dotty/tools/dotc/staging/TreeMapWithStages.scala

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,17 @@ abstract class TreeMapWithStages extends TreeMapWithImplicits {
2424
/** Transform the quote `quote` which contains the quoted `body`.
2525
*
2626
* - `quoted.runtime.Expr.quote[T](<body0>)` --> `quoted.runtime.Expr.quote[T](<body>)`
27+
*/
28+
protected def transformQuotedExpr(body: Tree, quote: Apply)(using Context): Tree =
29+
cpy.Apply(quote)(quote.fun, body :: Nil)
30+
31+
/** Transform the quote `quote` which contains the quoted `body`.
32+
*
2733
* - `quoted.Type.of[<body0>](quotes)` --> `quoted.Type.of[<body>](quotes)`
2834
*/
29-
protected def transformQuotation(body: Tree, quote: Apply)(using Context): Tree =
30-
if body.isTerm then
31-
cpy.Apply(quote)(quote.fun, body :: Nil)
32-
else
33-
val TypeApply(fun, _) = quote.fun: @unchecked
34-
cpy.Apply(quote)(cpy.TypeApply(quote.fun)(fun, body :: Nil), quote.args)
35+
protected def transformQuotedType(body: Tree, quote: Apply)(using Context): Tree =
36+
val TypeApply(fun, _) = quote.fun: @unchecked
37+
cpy.Apply(quote)(cpy.TypeApply(quote.fun)(fun, body :: Nil), quote.args)
3538

3639
/** Transform the expression splice `splice` which contains the spliced `body`. */
3740
protected def transformSplice(body: Tree, splice: Apply)(using Context): Tree
@@ -56,7 +59,7 @@ abstract class TreeMapWithStages extends TreeMapWithImplicits {
5659
case tree @ QuotedTypeOf(quotedTree) =>
5760
val old = inQuoteOrSplice
5861
inQuoteOrSplice = true
59-
try transformQuotation(quotedTree, tree)
62+
try transformQuotedType(quotedTree, tree)
6063
finally inQuoteOrSplice = old
6164

6265
case tree @ QuotedExpr(quotedTree) =>
@@ -67,7 +70,8 @@ abstract class TreeMapWithStages extends TreeMapWithImplicits {
6770
// Optimization: `'{ $x }` --> `x`
6871
// and adapt the refinement of `Quotes { type reflect: ... } ?=> Expr[T]`
6972
transform(t).asInstance(tree.tpe)
70-
case _ => transformQuotation(quotedTree, tree)
73+
case _ =>
74+
transformQuotedExpr(quotedTree, tree)
7175
}
7276
finally inQuoteOrSplice = old
7377

0 commit comments

Comments
 (0)