Skip to content

Commit 8a9871f

Browse files
committed
Simplify Quote/Splice transformations in CrossStageSafety
1 parent 3097f49 commit 8a9871f

File tree

3 files changed

+40
-38
lines changed

3 files changed

+40
-38
lines changed

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,17 @@ object Trees {
714714
defn.FunctionType(1, isContextual = true)
715715
.appliedTo(defn.QuotesClass.typeRef, exprType)
716716
withType(quoteType)
717+
718+
/** Cancel this Quote if it contains a Splice */
719+
def cancelled(using Context): Option[Tree[T]] =
720+
def rec(tree: Tree[T]): Option[Tree[T]] = tree match
721+
case Block(Nil, expr) => rec(expr)
722+
case Splice(inner) =>
723+
// Optimization: `'{ $x }` --> `x`
724+
// and adapt the refinement of `Quotes { type reflect: ... } ?=> Expr[T]`
725+
Some(inner)
726+
case _ => None
727+
rec(body)
717728
}
718729

719730
/** A tree representing a splice `${ expr }`
@@ -730,6 +741,16 @@ object Trees {
730741
case class Splice[+T <: Untyped] private[ast] (expr: Tree[T])(implicit @constructorOnly src: SourceFile)
731742
extends TermTree[T] {
732743
type ThisTree[+T <: Untyped] = Splice[T]
744+
745+
/** Cancel this Splice if it contains a Quote */
746+
def cancelled(using Context): Option[Tree[T]] =
747+
def rec(tree: Tree[T]): Option[Tree[T]] = tree match
748+
case Block(Nil, expr1) => rec(expr1)
749+
case Quote(body) =>
750+
// Optimization: `${ 'x }` --> `x`
751+
Some(body)
752+
case _ => None
753+
rec(expr)
733754
}
734755

735756
/** A type tree that represents an existing or inferred type */

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ class CrossStageSafety extends TreeMapWithStages {
5353
else if !inQuoteOrSpliceScope then
5454
checkAnnotations(tree)
5555
tree match
56+
case tree @ Quote(quotedTree) =>
57+
tree.cancelled match
58+
case Some(tree1) => transform(tree1.asInstance(tree.tpe)) // TODO is this asInstance still needed?
59+
case None => transformQuote(quotedTree, tree)
60+
case tree @ Splice(splicedTree) =>
61+
tree.cancelled match
62+
case Some(tree1) => transform(tree1)
63+
case None => transformSplice(splicedTree, tree)
5664
case tree @ QuotedTypeOf(quotedTree) =>
5765
transformQuotedType(quotedTree, tree)
5866
case _ => super.transform(tree)
@@ -95,6 +103,14 @@ class CrossStageSafety extends TreeMapWithStages {
95103
case tree: TypeDef if tree.symbol.is(Case) && level > 0 =>
96104
report.error(reporting.CaseClassInInlinedCode(tree), tree)
97105
super.transform(tree)
106+
case tree @ Quote(quotedTree) =>
107+
tree.cancelled match
108+
case Some(tree1) => transform(tree1.asInstance(tree.tpe)) // TODO is this asInstance still needed?
109+
case None => transformQuote(quotedTree, tree)
110+
case tree @ Splice(splicedTree) =>
111+
tree.cancelled match
112+
case Some(tree1) => transform(tree1)
113+
case None => transformSplice(splicedTree, tree)
98114
case tree @ QuotedTypeOf(quotedTree) =>
99115
transformQuotedType(quotedTree, tree)
100116
case tree @ SplicedType(splicedTree) =>
@@ -104,7 +120,7 @@ class CrossStageSafety extends TreeMapWithStages {
104120
}
105121

106122
/** Transform quoted trees while maintaining level correctness */
107-
override protected def transformQuote(body: Tree, quote: Quote)(using Context): Tree = {
123+
private def transformQuote(body: Tree, quote: Quote)(using Context): Tree = {
108124
if (ctx.property(InAnnotation).isDefined)
109125
report.error("Cannot have a quote in an annotation", quote.srcPos)
110126
val transformedBody = transformQuoteBody(body, quote.span)
@@ -150,7 +166,7 @@ class CrossStageSafety extends TreeMapWithStages {
150166
* - If inside inlined code, expand the macro code.
151167
* - If inside of a macro definition, check the validity of the macro.
152168
*/
153-
protected def transformSplice(body: Tree, splice: Splice)(using Context): Tree = {
169+
private def transformSplice(body: Tree, splice: Splice)(using Context): Tree = {
154170
val body1 = transform(body)(using spliceContext)
155171
val tpe1 =
156172
if level == 0 then splice.tpe

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

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import dotty.tools.dotc.config.Printers.staging
66
import dotty.tools.dotc.core.Decorators._
77
import dotty.tools.dotc.core.Contexts._
88
import dotty.tools.dotc.core.Symbols._
9-
import dotty.tools.dotc.util.Property
109
import dotty.tools.dotc.staging.StagingLevel.*
1110

1211
import scala.collection.mutable
@@ -15,45 +14,11 @@ import scala.collection.mutable
1514
abstract class TreeMapWithStages extends TreeMapWithImplicits {
1615
import tpd._
1716

18-
/** Transform the quote `quote` which contains the quoted `body`.
19-
*
20-
* - `quoted.runtime.Expr.quote[T](<body0>)` --> `quoted.runtime.Expr.quote[T](<body>)`
21-
*/
22-
protected def transformQuote(body: Tree, quote: Quote)(using Context): Tree =
23-
cpy.Quote(quote)(body)
24-
25-
/** Transform the expression splice `splice` which contains the spliced `body`. */
26-
protected def transformSplice(body: Tree, splice: Splice)(using Context): Tree
27-
2817
override def transform(tree: Tree)(using Context): Tree =
2918
if (tree.source != ctx.source && tree.source.exists)
3019
transform(tree)(using ctx.withSource(tree.source))
31-
else reporting.trace(i"StagingTransformer.transform $tree at $level", staging, show = true) {
32-
def dropEmptyBlocks(tree: Tree): Tree = tree match {
33-
case Block(Nil, expr) => dropEmptyBlocks(expr)
34-
case _ => tree
35-
}
36-
20+
else reporting.trace(i"TreeMapWithStages.transform $tree at $level", staging, show = true) {
3721
tree match {
38-
case tree @ Quote(quotedTree) =>
39-
dropEmptyBlocks(quotedTree) match {
40-
case Splice(t) =>
41-
// Optimization: `'{ $x }` --> `x`
42-
// and adapt the refinement of `Quotes { type reflect: ... } ?=> Expr[T]`
43-
transform(t).asInstance(tree.tpe)
44-
case _ =>
45-
transformQuote(quotedTree, tree)
46-
}
47-
48-
case tree @ Splice(splicedTree) =>
49-
dropEmptyBlocks(splicedTree) match {
50-
case Quote(t) =>
51-
// Optimization: `${ 'x }` --> `x`
52-
transform(t)
53-
case _ =>
54-
transformSplice(splicedTree, tree)
55-
}
56-
5722
case Block(stats, _) =>
5823
val defSyms = stats.collect { case defTree: DefTree => defTree.symbol }
5924
super.transform(tree)(using symbolsInCurrentLevel(defSyms))

0 commit comments

Comments
 (0)