Skip to content

Commit 6fbedc1

Browse files
committed
Do not optimize ${'{...}} in typer
This optimization is done later in the `Staging` phase
1 parent e7c734f commit 6fbedc1

File tree

6 files changed

+55
-65
lines changed

6 files changed

+55
-65
lines changed

compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala

Lines changed: 48 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ trait QuotesAndSplices { self: Typer =>
3535
* while tracking the quotation level in the context.
3636
*/
3737
def typedQuote(tree: untpd.Quote, pt: Type)(implicit ctx: Context): Tree = track("typedQuote") {
38+
ctx.compilationUnit.needsStaging = true
3839
tree.quoted match {
3940
case untpd.Splice(innerExpr) if tree.isTerm =>
4041
ctx.warning("Canceled splice directly inside a quote. '{ ${ XYZ } } is equivalent to XYZ.", tree.sourcePos)
4142
case untpd.TypSplice(innerType) if tree.isType =>
4243
ctx.warning("Canceled splice directly inside a quote. '[ ${ XYZ } ] is equivalent to XYZ.", tree.sourcePos)
4344
case _ =>
4445
}
45-
ctx.compilationUnit.needsStaging = true
4646
val tree1 =
4747
if (tree.quoted.isType) typedTypeApply(untpd.TypeApply(untpd.ref(defn.InternalQuoted_typeQuote.termRef), tree.quoted :: Nil), pt)(quoteContext)
4848
else if (ctx.mode.is(Mode.Pattern) && level == 0) typedQuotePattern(tree, pt)
@@ -52,36 +52,35 @@ trait QuotesAndSplices { self: Typer =>
5252

5353
/** Translate `${ t: Expr[T] }` into expression `t.splice` while tracking the quotation level in the context */
5454
def typedSplice(tree: untpd.Splice, pt: Type)(implicit ctx: Context): Tree = track("typedSplice") {
55+
ctx.compilationUnit.needsStaging = true
5556
checkSpliceOutsideQuote(tree)
5657
tree.expr match {
5758
case untpd.Quote(innerExpr) if innerExpr.isTerm =>
5859
ctx.warning("Canceled quote directly inside a splice. ${ '{ XYZ } } is equivalent to XYZ.", tree.sourcePos)
59-
typed(innerExpr, pt)
60-
case expr =>
61-
ctx.compilationUnit.needsStaging = true
62-
if (ctx.mode.is(Mode.QuotedPattern) && level == 1) {
63-
if (isFullyDefined(pt, ForceDegree.all)) {
64-
def spliceOwner(ctx: Context): Symbol =
65-
if (ctx.mode.is(Mode.QuotedPattern)) spliceOwner(ctx.outer) else ctx.owner
66-
val pat = typedPattern(expr, defn.QuotedExprClass.typeRef.appliedTo(pt))(
67-
spliceContext.retractMode(Mode.QuotedPattern).withOwner(spliceOwner(ctx)))
68-
Splice(pat)
69-
} else {
70-
ctx.error(i"Type must be fully defined.\nConsider annotating the splice using a type ascription:\n ($tree: XYZ).", expr.sourcePos)
71-
tree.withType(UnspecifiedErrorType)
72-
}
73-
}
74-
else {
75-
if (StagingContext.level == 0) {
76-
// Mark the first inline method from the context as a macro
77-
def markAsMacro(c: Context): Unit =
78-
if (c.owner eq c.outer.owner) markAsMacro(c.outer)
79-
else if (c.owner.isInlineMethod) c.owner.setFlag(Macro)
80-
else if (!c.outer.owner.is(Package)) markAsMacro(c.outer)
81-
markAsMacro(ctx)
82-
}
83-
typedApply(untpd.Apply(untpd.ref(defn.InternalQuoted_exprSplice.termRef), tree.expr), pt)(spliceContext).withSpan(tree.span)
84-
}
60+
case _ =>
61+
}
62+
if (ctx.mode.is(Mode.QuotedPattern) && level == 1) {
63+
if (isFullyDefined(pt, ForceDegree.all)) {
64+
def spliceOwner(ctx: Context): Symbol =
65+
if (ctx.mode.is(Mode.QuotedPattern)) spliceOwner(ctx.outer) else ctx.owner
66+
val pat = typedPattern(tree.expr, defn.QuotedExprClass.typeRef.appliedTo(pt))(
67+
spliceContext.retractMode(Mode.QuotedPattern).withOwner(spliceOwner(ctx)))
68+
Splice(pat)
69+
} else {
70+
ctx.error(i"Type must be fully defined.\nConsider annotating the splice using a type ascription:\n ($tree: XYZ).", tree.expr.sourcePos)
71+
tree.withType(UnspecifiedErrorType)
72+
}
73+
}
74+
else {
75+
if (StagingContext.level == 0) {
76+
// Mark the first inline method from the context as a macro
77+
def markAsMacro(c: Context): Unit =
78+
if (c.owner eq c.outer.owner) markAsMacro(c.outer)
79+
else if (c.owner.isInlineMethod) c.owner.setFlag(Macro)
80+
else if (!c.outer.owner.is(Package)) markAsMacro(c.outer)
81+
markAsMacro(ctx)
82+
}
83+
typedApply(untpd.Apply(untpd.ref(defn.InternalQuoted_exprSplice.termRef), tree.expr), pt)(spliceContext).withSpan(tree.span)
8584
}
8685
}
8786

@@ -92,30 +91,29 @@ trait QuotesAndSplices { self: Typer =>
9291
tree.expr match {
9392
case untpd.Quote(innerType) if innerType.isType =>
9493
ctx.warning("Canceled quote directly inside a splice. ${ '[ XYZ ] } is equivalent to XYZ.", tree.sourcePos)
95-
typed(innerType, pt)
96-
case expr =>
97-
if (ctx.mode.is(Mode.QuotedPattern) && level == 1) {
98-
if (isFullyDefined(pt, ForceDegree.all)) {
99-
ctx.error(i"Spliced type pattern must not be fully defined. Consider using $pt directly", tree.expr.sourcePos)
100-
tree.withType(UnspecifiedErrorType)
101-
} else {
102-
def spliceOwner(ctx: Context): Symbol =
103-
if (ctx.mode.is(Mode.QuotedPattern)) spliceOwner(ctx.outer) else ctx.owner
104-
val name = expr match {
105-
case Ident(name) => ("$" + name).toTypeName
106-
case Typed(Ident(name), _) => ("$" + name).toTypeName
107-
case Bind(name, _) => ("$" + name).toTypeName
108-
case _ => NameKinds.UniqueName.fresh("$".toTypeName)
109-
}
110-
val typeSym = ctx.newSymbol(spliceOwner(ctx), name, EmptyFlags, TypeBounds.empty, NoSymbol, expr.span)
111-
typeSym.addAnnotation(Annotation(New(ref(defn.InternalQuoted_patternBindHoleAnnot.typeRef)).withSpan(expr.span)))
112-
val pat = typedPattern(expr, defn.QuotedTypeClass.typeRef.appliedTo(typeSym.typeRef))(
113-
spliceContext.retractMode(Mode.QuotedPattern).withOwner(spliceOwner(ctx)))
114-
pat.select(tpnme.splice)
115-
}
116-
} else {
117-
typedSelect(untpd.Select(tree.expr, tpnme.splice), pt)(spliceContext).withSpan(tree.span)
94+
case _ =>
95+
}
96+
if (ctx.mode.is(Mode.QuotedPattern) && level == 1) {
97+
if (isFullyDefined(pt, ForceDegree.all)) {
98+
ctx.error(i"Spliced type pattern must not be fully defined. Consider using $pt directly", tree.expr.sourcePos)
99+
tree.withType(UnspecifiedErrorType)
100+
} else {
101+
def spliceOwner(ctx: Context): Symbol =
102+
if (ctx.mode.is(Mode.QuotedPattern)) spliceOwner(ctx.outer) else ctx.owner
103+
val name = tree.expr match {
104+
case Ident(name) => ("$" + name).toTypeName
105+
case Typed(Ident(name), _) => ("$" + name).toTypeName
106+
case Bind(name, _) => ("$" + name).toTypeName
107+
case _ => NameKinds.UniqueName.fresh("$".toTypeName)
118108
}
109+
val typeSym = ctx.newSymbol(spliceOwner(ctx), name, EmptyFlags, TypeBounds.empty, NoSymbol, tree.expr.span)
110+
typeSym.addAnnotation(Annotation(New(ref(defn.InternalQuoted_patternBindHoleAnnot.typeRef)).withSpan(tree.expr.span)))
111+
val pat = typedPattern(tree.expr, defn.QuotedTypeClass.typeRef.appliedTo(typeSym.typeRef))(
112+
spliceContext.retractMode(Mode.QuotedPattern).withOwner(spliceOwner(ctx)))
113+
pat.select(tpnme.splice)
114+
}
115+
} else {
116+
typedSelect(untpd.Select(tree.expr, tpnme.splice), pt)(spliceContext).withSpan(tree.span)
119117
}
120118
}
121119

tests/neg/i4431.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import scala.quoted._
2+
3+
object Macros {
4+
inline def h(f: => Int => String): String = ${'{f(42)}} // error
5+
}

tests/run-macros/i4431/quoted_1.scala

Lines changed: 0 additions & 5 deletions
This file was deleted.

tests/run-macros/i4431/quoted_2.scala

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
((qctx: scala.quoted.QuoteContext) => {
22
val a: scala.quoted.Expr[scala.Int] = '{4} given (qctx)
3-
((evidence$2: scala.quoted.QuoteContext) => a) given (qctx)
3+
((qctx2: scala.quoted.QuoteContext) => ((evidence$3: scala.quoted.QuoteContext) => a) given (qctx2)) given (qctx)
44
})

tests/run-with-compiler/quote-nested-5.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ object Test {
66

77
val q = '{ given (qctx: QuoteContext) =>
88
val a = '{4}
9-
${'{
9+
${'{ given (qctx2: QuoteContext) =>
1010
'{${a}}
1111
}}
1212

0 commit comments

Comments
 (0)