Skip to content

Commit 036096a

Browse files
authored
Merge pull request #6073 from dotty-staging/remove-splice-private-method
Remove splice internal representation from public API
2 parents 51fb89d + 59a170e commit 036096a

File tree

22 files changed

+125
-66
lines changed

22 files changed

+125
-66
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -824,8 +824,11 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
824824
* The result can be the contents of a term or type splice, which
825825
* will return a term or type tree respectively.
826826
*/
827-
def unapply(tree: tpd.Select)(implicit ctx: Context): Option[tpd.Tree] =
828-
if (tree.symbol.isSplice) Some(tree.qualifier) else None
827+
def unapply(tree: tpd.Tree)(implicit ctx: Context): Option[tpd.Tree] = tree match {
828+
case tree: tpd.Apply if tree.symbol.isSplice => Some(tree.args.head)
829+
case tree: tpd.Select if tree.symbol.isSplice => Some(tree.qualifier)
830+
case _ => None
831+
}
829832
}
830833
}
831834

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,12 +704,13 @@ class Definitions {
704704

705705
lazy val QuotedExprType: TypeRef = ctx.requiredClassRef("scala.quoted.Expr")
706706
def QuotedExprClass(implicit ctx: Context): ClassSymbol = QuotedExprType.symbol.asClass
707-
lazy val QuotedExpr_splice : TermSymbol = QuotedExprClass.requiredMethod(nme.splice)
708707

709708
lazy val InternalQuotedModule: TermRef = ctx.requiredModuleRef("scala.internal.Quoted")
710709
def InternalQuotedModuleClass: Symbol = InternalQuotedModule.symbol
711710
lazy val InternalQuoted_exprQuoteR: TermRef = InternalQuotedModuleClass.requiredMethodRef("exprQuote".toTermName)
712711
def InternalQuoted_exprQuote(implicit ctx: Context): Symbol = InternalQuoted_exprQuoteR.symbol
712+
lazy val InternalQuoted_exprSpliceR: TermRef = InternalQuotedModuleClass.requiredMethodRef("exprSplice".toTermName)
713+
def InternalQuoted_exprSplice(implicit ctx: Context): Symbol = InternalQuoted_exprSpliceR.symbol
713714
lazy val InternalQuoted_typeQuoteR: TermRef = InternalQuotedModuleClass.requiredMethodRef("typeQuote".toTermName)
714715
def InternalQuoted_typeQuote(implicit ctx: Context): Symbol = InternalQuoted_typeQuoteR.symbol
715716

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
328328
if (name.isTypeName) typeText(txt)
329329
else txt
330330
case tree @ Select(qual, name) =>
331-
if (tree.hasType && tree.symbol == defn.QuotedExpr_splice) keywordStr("${") ~ toTextLocal(qual) ~ keywordStr("}")
332-
else if (tree.hasType && tree.symbol == defn.QuotedType_splice) typeText("${") ~ toTextLocal(qual) ~ typeText("}")
331+
if (tree.hasType && tree.symbol == defn.QuotedType_splice) typeText("${") ~ toTextLocal(qual) ~ typeText("}")
333332
else if (qual.isType) toTextLocal(qual) ~ "#" ~ typeText(toText(name))
334333
else toTextLocal(qual) ~ ("." ~ nameIdText(tree) provided (name != nme.CONSTRUCTOR || ctx.settings.YprintDebug.value))
335334
case tree: This =>
@@ -343,6 +342,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
343342
}
344343
else if (fun.hasType && fun.symbol == defn.InternalQuoted_exprQuote)
345344
keywordStr("'{") ~ toTextGlobal(args, ", ") ~ keywordStr("}")
345+
else if (fun.hasType && fun.symbol == defn.InternalQuoted_exprSplice)
346+
keywordStr("${") ~ toTextGlobal(args, ", ") ~ keywordStr("}")
346347
else
347348
toTextLocal(fun) ~ "(" ~ toTextGlobal(args, ", ") ~ ")"
348349
case tree: TypeApply =>

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

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,23 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
4949
* - If inside inlined code, expand the macro code.
5050
* - If inside of a macro definition, check the validity of the macro.
5151
*/
52-
protected def transformSplice(splice: Select)(implicit ctx: Context): Tree = {
52+
protected def transformSplice(body: Tree, splice: Tree)(implicit ctx: Context): Tree = {
5353
if (level >= 1) {
54-
val body1 = transform(splice.qualifier)(spliceContext)
55-
val splice1 = cpy.Select(splice)(body1, splice.name)
56-
if (splice1.isType) splice1
57-
else addSpliceCast(splice1)
54+
val body1 = transform(body)(spliceContext)
55+
splice match {
56+
case Apply(fun: TypeApply, _) if splice.isTerm =>
57+
// Type of the splice itsel must also be healed
58+
// internal.Quoted.expr[F[T]](... T ...) --> internal.Quoted.expr[F[$t]](... T ...)
59+
val tp = checkType(splice.sourcePos).apply(splice.tpe.widenTermRefExpr)
60+
cpy.Apply(splice)(cpy.TypeApply(fun)(fun.fun, tpd.TypeTree(tp) :: Nil), body1 :: Nil)
61+
case splice: Select => cpy.Select(splice)(body1, splice.name)
62+
}
5863
}
5964
else {
6065
assert(!enclosingInlineds.nonEmpty, "unexpanded macro")
6166
assert(ctx.owner.isInlineMethod)
62-
if (Splicer.canBeSpliced(splice.qualifier)) { // level 0 inside an inline definition
63-
transform(splice.qualifier)(spliceContext) // Just check PCP
67+
if (Splicer.canBeSpliced(body)) { // level 0 inside an inline definition
68+
transform(body)(spliceContext) // Just check PCP
6469
splice
6570
}
6671
else { // level 0 inside an inline definition
@@ -72,15 +77,6 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
7277
}
7378
}
7479

75-
76-
/** Add cast to force boundaries where T and $t (an alias of T) are used to ensure PCP.
77-
* '{ ${...: T} } --> '{ ${...: T}.asInstanceOf[T] } --> '{ ${...: T}.asInstanceOf[$t] }
78-
*/
79-
protected def addSpliceCast(tree: Tree)(implicit ctx: Context): Tree = {
80-
val tp = checkType(tree.sourcePos).apply(tree.tpe.widenTermRefExpr)
81-
tree.cast(tp).withSpan(tree.span)
82-
}
83-
8480
/** If `tree` refers to a locally defined symbol (either directly, or in a pickled type),
8581
* check that its staging level matches the current level. References to types
8682
* that are phase-incorrect can still be healed as follows:

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

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ class ReifyQuotes extends MacroTransform {
170170
*/
171171
override protected def transformQuotation(body: Tree, quote: Tree)(implicit ctx: Context): Tree = {
172172
val isType = quote.symbol eq defn.InternalQuoted_typeQuote
173-
assert(!body.symbol.isSplice)
173+
assert(!(body.symbol.isSplice && (body.isInstanceOf[GenericApply[_]] || body.isInstanceOf[Select])))
174174
if (level > 0) {
175175
val body1 = nested(isQuote = true).transform(body)(quoteContext)
176176
super.transformQuotation(body1, quote)
@@ -222,21 +222,24 @@ class ReifyQuotes extends MacroTransform {
222222
* and make a hole from these parts. Otherwise issue an error, unless we
223223
* are in the body of an inline method.
224224
*/
225-
protected def transformSplice(splice: Select)(implicit ctx: Context): Tree = {
225+
protected def transformSplice(body: Tree, splice: Tree)(implicit ctx: Context): Tree = {
226226
if (level > 1) {
227-
val body1 = nested(isQuote = false).transform(splice.qualifier)(spliceContext)
228-
body1.select(splice.name)
227+
val body1 = nested(isQuote = false).transform(body)(spliceContext)
228+
splice match {
229+
case splice: Apply => cpy.Apply(splice)(splice.fun, body1 :: Nil)
230+
case splice: Select => cpy.Select(splice)(body1, splice.name)
231+
}
229232
}
230233
else {
231234
assert(level == 1, "unexpected top splice outside quote")
232-
val (body1, quotes) = nested(isQuote = false).splitSplice(splice.qualifier)(spliceContext)
233-
val tpe = outer.embedded.getHoleType(splice)
235+
val (body1, quotes) = nested(isQuote = false).splitSplice(body)(spliceContext)
236+
val tpe = outer.embedded.getHoleType(body, splice)
234237
val hole = makeHole(body1, quotes, tpe).withSpan(splice.span)
235238
// We do not place add the inline marker for trees that where lifted as they come from the same file as their
236239
// enclosing quote. Any intemediate splice will add it's own Inlined node and cancel it before splicig the lifted tree.
237240
// Note that lifted trees are not necessarily expressions and that Inlined nodes are expected to be expressions.
238241
// For example we can have a lifted tree containing the LHS of an assignment (see tests/run-with-compiler/quote-var.scala).
239-
if (splice.isType || outer.embedded.isLiftedSymbol(splice.qualifier.symbol)) hole
242+
if (splice.isType || outer.embedded.isLiftedSymbol(body.symbol)) hole
240243
else Inlined(EmptyTree, Nil, hole).withSpan(splice.span)
241244
}
242245
}
@@ -346,14 +349,13 @@ class ReifyQuotes extends MacroTransform {
346349
override def transform(tree: Tree)(implicit ctx: Context): Tree =
347350
reporting.trace(i"Reifier.transform $tree at $level", show = true) {
348351
tree match {
349-
case TypeApply(Select(spliceTree @ Spliced(_), _), tp) if tree.symbol.isTypeCast =>
350-
// Splice term which should be in the form `${x}.asInstanceOf[T]` where T is an artifact of
351-
// typer to allow pickling/unpickling phase consistent types
352-
transformSplice(spliceTree)
353-
354352
case tree: RefTree if isCaptured(tree.symbol, level) =>
355-
val t = capturers(tree.symbol).apply(tree)
356-
transformSplice(t.select(if (tree.isTerm) nme.splice else tpnme.splice))
353+
val body = capturers(tree.symbol).apply(tree)
354+
val splice: Tree =
355+
if (tree.isType) body.select(tpnme.splice)
356+
else ref(defn.InternalQuoted_exprSplice).appliedToType(tree.tpe).appliedTo(body)
357+
358+
transformSplice(body, splice)
357359

358360
case tree: DefDef if tree.symbol.is(Macro) && level == 0 =>
359361
// Shrink size of the tree. The methods have already been inlined.
@@ -396,11 +398,11 @@ object ReifyQuotes {
396398
}
397399

398400
/** Type used for the hole that will replace this splice */
399-
def getHoleType(splice: tpd.Select)(implicit ctx: Context): Type = {
401+
def getHoleType(body: tpd.Tree, splice: tpd.Tree)(implicit ctx: Context): Type = {
400402
// For most expressions the splice.tpe but there are some types that are lost by lifting
401403
// that can be recoverd from the original tree. Currently the cases are:
402404
// * Method types: the splice represents a method reference
403-
map.get(splice.qualifier.symbol).map(_.tpe.widen).getOrElse(splice.tpe)
405+
map.get(body.symbol).map(_.tpe.widen).getOrElse(splice.tpe)
404406
}
405407

406408
def isLiftedSymbol(sym: Symbol)(implicit ctx: Context): Boolean = map.contains(sym)

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ class Staging extends MacroTransform {
4444
tree match {
4545
case PackageDef(pid, _) if tree.symbol.owner == defn.RootClass =>
4646
val checker = new PCPCheckAndHeal(freshStagingContext) {
47-
override protected def addSpliceCast(tree: Tree)(implicit ctx: Context): Tree = tree
48-
4947
override protected def tryHeal(sym: Symbol, tp: Type, pos: SourcePosition)(implicit ctx: Context): Option[tpd.Tree] = {
5048
def symStr =
5149
if (!tp.isInstanceOf[ThisType]) sym.show

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,5 +157,5 @@ class SymUtils(val self: Symbol) extends AnyVal {
157157

158158
/** Is symbol a splice operation? */
159159
def isSplice(implicit ctx: Context): Boolean =
160-
self == defn.QuotedExpr_splice || self == defn.QuotedType_splice
160+
self == defn.InternalQuoted_exprSplice || self == defn.QuotedType_splice
161161
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ abstract class TreeMapWithStages(@constructorOnly ictx: Context) extends TreeMap
6464
}
6565
}
6666

67-
/** Transform the splice `splice`. */
68-
protected def transformSplice(splice: Select)(implicit ctx: Context): Tree
67+
/** Transform the splice `splice` which contains the spliced `body`. */
68+
protected def transformSplice(body: Tree, splice: Tree)(implicit ctx: Context): Tree
6969

7070
override def transform(tree: Tree)(implicit ctx: Context): Tree = {
7171
reporting.trace(i"StagingTransformer.transform $tree at $level", show = true) {
@@ -93,7 +93,7 @@ abstract class TreeMapWithStages(@constructorOnly ictx: Context) extends TreeMap
9393
case tree @ Spliced(splicedTree) =>
9494
dropEmptyBlocks(splicedTree) match {
9595
case Quoted(t) => transform(t) // ${ 'x } --> x
96-
case _ => transformSplice(tree)
96+
case _ => transformSplice(splicedTree, tree)
9797
}
9898

9999
case Block(stats, _) =>

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

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -968,21 +968,11 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
968968
override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = {
969969
assert(tree.hasType, tree)
970970
val qual1 = typed(tree.qualifier, selectionProto(tree.name, pt, this))
971-
val res =
972-
if (tree.symbol == defn.QuotedExpr_splice && level == 0) expandMacro(qual1, tree.span)
973-
else untpd.cpy.Select(tree)(qual1, tree.name).withType(tree.typeOpt)
971+
val res = untpd.cpy.Select(tree)(qual1, tree.name).withType(tree.typeOpt)
974972
ensureAccessible(res.tpe, tree.qualifier.isInstanceOf[untpd.Super], tree.sourcePos)
975973
res
976974
}
977975

978-
private def expandMacro(body: Tree, span: Span)(implicit ctx: Context) = {
979-
assert(level == 0)
980-
val inlinedFrom = enclosingInlineds.last
981-
val evaluatedSplice = Splicer.splice(body, inlinedFrom.sourcePos, MacroClassLoader.fromContext)(ctx.withSource(inlinedFrom.source))
982-
if (ctx.reporter.hasErrors) EmptyTree
983-
else evaluatedSplice.withSpan(span)
984-
}
985-
986976
override def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context): Tree =
987977
typed(tree.cond, defn.BooleanType) match {
988978
case cond1 @ ConstantValue(b: Boolean) =>
@@ -1001,8 +991,13 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
1001991
}
1002992
}
1003993

1004-
override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree =
1005-
constToLiteral(betaReduce(super.typedApply(tree, pt)))
994+
override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = {
995+
constToLiteral(betaReduce(super.typedApply(tree, pt))) match {
996+
case res: Apply if res.symbol == defn.InternalQuoted_exprSplice && level == 0 =>
997+
expandMacro(res.args.head, tree.span)
998+
case res => res
999+
}
1000+
}
10061001

10071002
override def typedMatchFinish(tree: untpd.Match, sel: Tree, wideSelType: Type, cases: List[untpd.CaseDef], pt: Type)(implicit ctx: Context) =
10081003
if (!tree.isInline || ctx.owner.isInlineMethod) // don't reduce match of nested inline method yet
@@ -1159,4 +1154,13 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
11591154
inlineTermBindings(termBindings1.asInstanceOf[List[ValOrDefDef]], tree1)
11601155
}
11611156
}
1157+
1158+
private def expandMacro(body: Tree, span: Span)(implicit ctx: Context) = {
1159+
assert(level == 0)
1160+
val inlinedFrom = enclosingInlineds.last
1161+
val evaluatedSplice = Splicer.splice(body, inlinedFrom.sourcePos, MacroClassLoader.fromContext)(ctx.withSource(inlinedFrom.source))
1162+
if (ctx.reporter.hasErrors) EmptyTree
1163+
else evaluatedSplice.withSpan(span)
1164+
}
1165+
11621166
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ object PrepareInlineable {
270270

271271
var isMacro = false
272272
new TreeMapWithStages(freshStagingContext) {
273-
override protected def transformSplice(splice: tpd.Select)(implicit ctx: Context): tpd.Tree = {
273+
override protected def transformSplice(body: tpd.Tree, splice: tpd.Tree)(implicit ctx: Context): tpd.Tree = {
274274
isMacro = true
275275
splice
276276
}

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1926,7 +1926,7 @@ class Typer extends Namer
19261926
}
19271927
}
19281928

1929-
/** Translate '{ t }` into `scala.quoted.Expr.apply(t)` and `'[T]` into `scala.quoted.Type.apply[T]`
1929+
/** Translate `'{ t }` into `scala.quoted.Expr.apply(t)` and `'[T]` into `scala.quoted.Type.apply[T]`
19301930
* while tracking the quotation level in the context.
19311931
*/
19321932
def typedQuote(tree: untpd.Quote, pt: Type)(implicit ctx: Context): Tree = track("typedQuote") {
@@ -1941,15 +1941,15 @@ class Typer extends Namer
19411941
}
19421942
}
19431943

1944-
/** Translate `${ t: Expr[T] }` into expresiion `t.splice` while tracking the quotation level in the context */
1944+
/** Translate `${ t: Expr[T] }` into expression `t.splice` while tracking the quotation level in the context */
19451945
def typedSplice(tree: untpd.Splice, pt: Type)(implicit ctx: Context): Tree = track("typedSplice") {
19461946
checkSpliceOutsideQuote(tree)
19471947
tree.expr match {
19481948
case untpd.Quote(innerExpr) =>
19491949
ctx.warning("Canceled quote directly inside a splice. ${ '{ XYZ } } is equivalent to XYZ.", tree.sourcePos)
19501950
typed(innerExpr, pt)
19511951
case expr =>
1952-
typedSelect(untpd.Select(expr, nme.splice), pt)(spliceContext).withSpan(tree.span)
1952+
typedApply(untpd.Apply(untpd.ref(defn.InternalQuoted_exprSpliceR), tree.expr), pt)(spliceContext).withSpan(tree.span)
19531953
}
19541954
}
19551955

@@ -1961,7 +1961,14 @@ class Typer extends Namer
19611961

19621962
private def checkSpliceOutsideQuote(tree: untpd.Tree)(implicit ctx: Context): Unit = {
19631963
if (level == 0 && !ctx.owner.isInlineMethod)
1964-
ctx.error("splice outside quotes or inline method", tree.sourcePos)
1964+
ctx.error("Splice ${...} outside quotes '{...} or inline method", tree.sourcePos)
1965+
else if (level < 0)
1966+
ctx.error(
1967+
"""Splice ${...} at level -1.
1968+
|
1969+
|Inline method may contain a splice at level 0 but the contents of this splice cannot have a splice.
1970+
|""".stripMargin, tree.sourcePos
1971+
)
19651972
}
19661973

19671974
/** Retrieve symbol attached to given tree */

library/src-bootstrapped/scala/StagedTuple.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ object StagedTuple {
203203
if (!specialize) '{dynamic_++[Self, That]($self, $that)}
204204
else {
205205
def genericConcat(xs: Expr[Tuple], ys: Expr[Tuple]): Expr[Tuple] =
206-
fromArrayStaged[Tuple]('{${ toArrayStaged(xs, None) } ++ ${ toArrayStaged(ys, None) }}, None)
206+
// TODO remove ascriptions when #6126 is fixed
207+
fromArrayStaged[Tuple]('{${ toArrayStaged(xs, None) } ++ (${ toArrayStaged(ys, None) }: Array[Object])}, None)
207208

208209
val res = selfSize match {
209210
case Some(0) =>

library/src-bootstrapped/scala/internal/Quoted.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ object Quoted {
88
def exprQuote[T](x: T): Expr[T] =
99
throw new Error("Internal error: this method call should have been replaced by the compiler")
1010

11+
/** A term splice is desugared by the compiler into a call to this method */
12+
def exprSplice[T](x: Expr[T]): T =
13+
throw new Error("Internal error: this method call should have been replaced by the compiler")
14+
1115
/** A type quote is desugared by the compiler into a call to this method */
1216
def typeQuote[T <: AnyKind]: Type[T] =
1317
throw new Error("Internal error: this method call should have been replaced by the compiler")

library/src-non-bootstrapped/scala/internal/Quoted.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ object Quoted {
88
def exprQuote[T](x: T): Expr[T] =
99
throw new Error("Internal error: this method call should have been replaced by the compiler")
1010

11+
/** A term splice is desugared by the compiler into a call to this method */
12+
def exprSplice[T](x: Expr[T]): T =
13+
throw new Error("Internal error: this method call should have been replaced by the compiler")
14+
1115
/** A type quote is desugared by the compiler into a call to this method */
1216
def typeQuote[T/* <: AnyKind */]: Type[T] =
1317
throw new Error("Internal error: this method call should have been replaced by the compiler")

library/src/scala/quoted/Expr.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import scala.runtime.quoted.Unpickler.Pickled
44

55
sealed abstract class Expr[+T] {
66

7-
final def `$splice`: T = throw new Error("splice should have been compiled away")
8-
97
/** Evaluate the contents of this expression and return the result.
108
*
119
* May throw a FreeVariableError on expressions that came from a macro.

tests/pos/i4774f.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ object Test {
66
'{ def y: T = $x; ${ loop('y) } }
77

88
def loop2[T](x: Expr[T])(implicit t: Type[T]): Expr[T] =
9-
'{ def y(): T = $x; ${ loop('{y()}) } }
9+
'{ def y(): T = $x; ${ loop2('{y()}) } }
1010
}

tests/pos/quote-nested.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import scala.annotation.tailrec
2+
import scala.quoted._
3+
4+
object Macro {
5+
6+
inline def foo: Unit = ${ nested() }
7+
8+
private def nested(): Expr[Unit] = '{
9+
var i = 0
10+
${
11+
val x: Expr[Double] = '{
12+
val y: Boolean = ${
13+
val z: Expr[Int] = '{i + 3}
14+
'{true}
15+
}
16+
4.2
17+
}
18+
'{}
19+
}
20+
()
21+
}
22+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
import scala.quoted._
3+
4+
object Macro {
5+
6+
inline def charOrString(inline str: String) <: Any = ${ impl(str) }
7+
8+
def impl(str: String) = if (str.length == 1) str.charAt(0).toExpr else str.toExpr
9+
10+
}

0 commit comments

Comments
 (0)