Skip to content

Commit fd3e321

Browse files
Merge pull request #8281 from dotty-staging/fix-#8045
Fix #8045: Refine QuoteContext{val tasty} provided by splices
2 parents e7847aa + fa4eef6 commit fd3e321

File tree

17 files changed

+147
-37
lines changed

17 files changed

+147
-37
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1228,7 +1228,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
12281228
val argType =
12291229
if (baseType != NoType) baseType.argTypesHi.head
12301230
else defn.NothingType
1231-
ref(defn.InternalQuoted_exprSplice).appliedToType(argType).appliedTo(tree)
1231+
ref(defn.InternalQuoted_exprSplice).appliedToTypes(List(argType, defn.QuoteContextClass.typeRef)).appliedTo(tree)
12321232
}
12331233
def unapply(tree: Tree)(implicit ctx: Context): Option[Tree] = tree match {
12341234
case Apply(fn, arg :: Nil) if fn.symbol == defn.InternalQuoted_exprSplice => Some(arg)

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

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package dotty.tools.dotc.core
22

33
import dotty.tools.dotc.core.Contexts._
4+
import dotty.tools.dotc.ast.tpd
45
import dotty.tools.dotc.util.Property
56

67
import scala.collection.mutable
@@ -10,6 +11,11 @@ object StagingContext {
1011
/** A key to be used in a context property that tracks the quoteation level */
1112
private val QuotationLevel = new Property.Key[Int]
1213

14+
/** A key to be used in a context property that tracks the quoteation stack.
15+
* Stack containing the QuoteContext references recieved by the surrounding quotes.
16+
*/
17+
private val QuoteContextStack = new Property.Key[List[tpd.Tree]]
18+
1319
/** All enclosing calls that are currently inlined, from innermost to outermost. */
1420
def level(implicit ctx: Context): Int =
1521
ctx.property(QuotationLevel).getOrElse(0)
@@ -18,8 +24,27 @@ object StagingContext {
1824
def quoteContext(implicit ctx: Context): Context =
1925
ctx.fresh.setProperty(QuotationLevel, level + 1)
2026

27+
/** Context with an incremented quotation level and pushes a refecence to a QuoteContext on the quote context stack */
28+
def pushQuoteContext(qctxRef: tpd.Tree)(implicit ctx: Context): Context =
29+
val old = ctx.property(QuoteContextStack).getOrElse(List.empty)
30+
ctx.fresh.setProperty(QuotationLevel, level + 1)
31+
.setProperty(QuoteContextStack, qctxRef :: old)
32+
2133
/** Context with a decremented quotation level. */
2234
def spliceContext(implicit ctx: Context): Context =
2335
ctx.fresh.setProperty(QuotationLevel, level - 1)
24-
}
2536

37+
/** Context with a decremented quotation level and pops the Some of top of the quote context stack or None if the stack is empty.
38+
* The quotation stack could be empty if we are in a top level splice or an eroneous splice directly witin a top level splice.
39+
*/
40+
def popQuoteContext()(implicit ctx: Context): (Option[tpd.Tree], Context) =
41+
val ctx1 = ctx.fresh.setProperty(QuotationLevel, level - 1)
42+
val head =
43+
ctx.property(QuoteContextStack) match
44+
case Some(x :: xs) =>
45+
ctx1.setProperty(QuoteContextStack, xs)
46+
Some(x)
47+
case _ =>
48+
None // Splice at level 0 or lower
49+
(head, ctx1)
50+
}

compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ object PickledQuotes {
6060
}.apply(tp)
6161

6262
/** Unpickle the tree contained in the TastyExpr */
63-
def unpickleExpr(tasty: PickledQuote, args: PickledExprArgs)(implicit ctx: Context): Tree = {
63+
def unpickleExpr(tasty: PickledQuote, args: PickledArgs)(implicit ctx: Context): Tree = {
6464
val tastyBytes = TastyString.unpickle(tasty)
6565
val unpickled = unpickle(tastyBytes, args, isType = false)(ctx.addMode(Mode.ReadPositions))
6666
/** Force unpickling of the tree, removes the spliced type `@quotedTypeTag type` definitions and dealiases references to `@quotedTypeTag type` */
@@ -76,7 +76,7 @@ object PickledQuotes {
7676
}
7777

7878
/** Unpickle the tree contained in the TastyType */
79-
def unpickleType(tasty: PickledQuote, args: PickledTypeArgs)(implicit ctx: Context): Tree = {
79+
def unpickleType(tasty: PickledQuote, args: PickledArgs)(implicit ctx: Context): Tree = {
8080
val tastyBytes = TastyString.unpickle(tasty)
8181
val unpickled = unpickle(tastyBytes, args, isType = true)(ctx.addMode(Mode.ReadPositions))
8282
val tpt = unpickled match {

compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend
3535
// QUOTE UNPICKLING //
3636
//////////////////////
3737

38-
def unpickleExpr(repr: Unpickler.PickledQuote, args: Unpickler.PickledExprArgs): scala.quoted.Expr[?] =
38+
def unpickleExpr(repr: Unpickler.PickledQuote, args: Unpickler.PickledArgs): scala.quoted.Expr[?] =
3939
new TastyTreeExpr(PickledQuotes.unpickleExpr(repr, args), compilerId)
4040

41-
def unpickleType(repr: Unpickler.PickledQuote, args: Unpickler.PickledTypeArgs): scala.quoted.Type[?] =
41+
def unpickleType(repr: Unpickler.PickledQuote, args: Unpickler.PickledArgs): scala.quoted.Type[?] =
4242
new TreeType(PickledQuotes.unpickleType(repr, args), compilerId)
4343

4444

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
6868
protected def transformSplice(body: Tree, splice: Tree)(implicit ctx: Context): Tree = {
6969
val body1 = transform(body)(spliceContext)
7070
splice match {
71-
case Apply(fun: TypeApply, _) if splice.isTerm =>
71+
case Apply(fun @ TypeApply(_, _ :: qctx :: Nil), _) if splice.isTerm =>
7272
// Type of the splice itsel must also be healed
7373
// internal.Quoted.expr[F[T]](... T ...) --> internal.Quoted.expr[F[$t]](... T ...)
7474
val tp = checkType(splice.sourcePos).apply(splice.tpe.widenTermRefExpr)
75-
cpy.Apply(splice)(cpy.TypeApply(fun)(fun.fun, tpd.TypeTree(tp) :: Nil), body1 :: Nil)
75+
cpy.Apply(splice)(cpy.TypeApply(fun)(fun.fun, tpd.TypeTree(tp) :: qctx :: Nil), body1 :: Nil)
7676
case splice: Select => cpy.Select(splice)(body1, splice.name)
7777
}
7878
}

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,8 @@ class ReifyQuotes extends MacroTransform {
230230
val meth =
231231
if (isType) ref(defn.Unpickler_unpickleType).appliedToType(originalTp)
232232
else ref(defn.Unpickler_unpickleExpr).appliedToType(originalTp.widen)
233-
val spliceResType =
234-
if (isType) defn.QuotedTypeClass.typeRef.appliedTo(WildcardType)
235-
else defn.FunctionType(1, isContextual = true).appliedTo(defn.QuoteContextClass.typeRef, defn.QuotedExprClass.typeRef.appliedTo(defn.AnyType)) | defn.QuotedTypeClass.typeRef.appliedTo(WildcardType)
236233
val pickledQuoteStrings = liftList(PickledQuotes.pickleQuote(body).map(x => Literal(Constant(x))), defn.StringType)
237-
val splicesList = liftList(splices, defn.FunctionType(1).appliedTo(defn.SeqType.appliedTo(defn.AnyType), spliceResType))
234+
val splicesList = liftList(splices, defn.FunctionType(1).appliedTo(defn.SeqType.appliedTo(defn.AnyType), defn.AnyType))
238235
meth.appliedTo(pickledQuoteStrings, splicesList)
239236
}
240237

@@ -394,7 +391,7 @@ class ReifyQuotes extends MacroTransform {
394391
val body = capturers(tree.symbol).apply(tree)
395392
val splice: Tree =
396393
if (tree.isType) body.select(tpnme.splice)
397-
else ref(defn.InternalQuoted_exprSplice).appliedToType(tree.tpe).appliedTo(body)
394+
else ref(defn.InternalQuoted_exprSplice).appliedToTypes(List(tree.tpe, defn.QuoteContextClass.typeRef)).appliedTo(body)
398395

399396
transformSplice(body, splice)
400397

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ abstract class TreeMapWithStages(@constructorOnly ictx: Context) extends TreeMap
9090

9191
case Quoted(quotedTree) =>
9292
dropEmptyBlocks(quotedTree) match {
93-
case Spliced(t) => transform(t) // '{ $x } --> x
93+
case Spliced(t) =>
94+
// '{ $x } --> x
95+
// and adapt the refinment of `QuoteContext { type tasty: ... } ?=> Expr[T]`
96+
transform(t).asInstance(tree.tpe)
9497
case _ => transformQuotation(quotedTree, tree)
9598
}
9699

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

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,16 @@ trait QuotesAndSplices {
4545
ctx.warning("Canceled splice directly inside a quote. '[ ${ XYZ } ] is equivalent to XYZ.", tree.sourcePos)
4646
case _ =>
4747
}
48+
val qctx = inferImplicitArg(defn.QuoteContextClass.typeRef, tree.span)
49+
if (level == 0 && qctx.tpe.isInstanceOf[SearchFailureType])
50+
ctx.error(missingArgMsg(qctx, defn.QuoteContextClass.typeRef, ""), ctx.source.atSpan(tree.span))
4851
val tree1 =
49-
if (ctx.mode.is(Mode.Pattern) && level == 0) typedQuotePattern(tree, pt)
50-
else if (tree.quoted.isType) typedTypeApply(untpd.TypeApply(untpd.ref(defn.InternalQuoted_typeQuote.termRef), tree.quoted :: Nil), pt)(quoteContext)
51-
else typedApply(untpd.Apply(untpd.ref(defn.InternalQuoted_exprQuote.termRef), tree.quoted), pt)(quoteContext)
52+
if ctx.mode.is(Mode.Pattern) && level == 0 then
53+
typedQuotePattern(tree, pt, qctx)
54+
else if (tree.quoted.isType)
55+
typedTypeApply(untpd.TypeApply(untpd.ref(defn.InternalQuoted_typeQuote.termRef), tree.quoted :: Nil), pt)(quoteContext)
56+
else
57+
typedApply(untpd.Apply(untpd.ref(defn.InternalQuoted_exprQuote.termRef), tree.quoted), pt)(pushQuoteContext(qctx)).select(nme.apply).appliedTo(qctx)
5258
tree1.withSpan(tree.span)
5359
}
5460

@@ -85,19 +91,23 @@ trait QuotesAndSplices {
8591
markAsMacro(ctx)
8692
}
8793

94+
val (outerQctx, ctx1) = popQuoteContext()
95+
8896
// Explicitly provide the given QuoteContext of the splice.
8997
// * Avoids leaking implementation details of scala.internal.quoted.CompileTime.exprSplice,
9098
// such as exprSplice taking a ?=> function argument
9199
// * Provide meaningful names for QuoteContext synthesized by within `${ ... }`
92-
// * TODO preserve QuoteContext.tasty path dependent type (see comment below and #8045)
93-
val qctxParamName = NameKinds.UniqueName.fresh(s"qctx${level - 1}_".toTermName)
94-
// TODO: Refine QuoteContext with the tasty context that the quote received
95-
// If encoloseing quote receives `qctx` then this type should be `QuoteContext { val tasty: qxtx.tasty.type }`
96-
val qctxParamTpt = untpd.TypedSplice(TypeTree(defn.QuoteContextClass.typeRef))
100+
// * If within a quote, provide a QuoteContext is linked typewise with the outer QuoteContext
101+
val qctxParamName = NameKinds.UniqueName.fresh(s"qctx${if level > 0 then level - 1 else ""}_".toTermName)
102+
val qctxParamTpe = outerQctx match {
103+
case Some(qctxRef) => qctxRef.tpe.select("NestedContext".toTypeName)
104+
case _ => defn.QuoteContextClass.typeRef // splice at level 0 (or lower)
105+
}
106+
val qctxParamTpt = untpd.TypedSplice(TypeTree(qctxParamTpe))
97107
val qctxParam = untpd.makeParameter(qctxParamName, qctxParamTpt, untpd.Modifiers(Given))
98108
val expr = untpd.Function(List(qctxParam), tree.expr).withSpan(tree.span)
99109

100-
typedApply(untpd.Apply(untpd.ref(defn.InternalQuoted_exprSplice.termRef), expr), pt)(spliceContext).withSpan(tree.span)
110+
typedApply(untpd.Apply(untpd.ref(defn.InternalQuoted_exprSplice.termRef), expr), pt)(ctx1).withSpan(tree.span)
101111
}
102112
}
103113

@@ -326,11 +336,7 @@ trait QuotesAndSplices {
326336
* ) => ...
327337
* ```
328338
*/
329-
private def typedQuotePattern(tree: untpd.Quote, pt: Type)(implicit ctx: Context): Tree = {
330-
val qctx = inferImplicitArg(defn.QuoteContextClass.typeRef, tree.span)
331-
if (level == 0 && qctx.tpe.isInstanceOf[SearchFailureType])
332-
ctx.error(missingArgMsg(qctx, defn.QuoteContextClass.typeRef, ""), ctx.source.atSpan(tree.span))
333-
339+
private def typedQuotePattern(tree: untpd.Quote, pt: Type, qctx: Tree)(implicit ctx: Context): Tree = {
334340
val quoted = tree.quoted
335341
val exprPt = pt.baseType(if quoted.isType then defn.QuotedTypeClass else defn.QuotedExprClass)
336342
val quotedPt = exprPt.argInfos.headOption match {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package scala.internal.quoted
2+
3+
import scala.annotation.{Annotation, compileTimeOnly}
4+
import scala.quoted._
5+
6+
@compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime`")
7+
object CompileTime {
8+
9+
/** A term quote is desugared by the compiler into a call to this method */
10+
@compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.exprQuote`")
11+
def exprQuote[T](x: T): QuoteContext ?=> Expr[T] = ???
12+
13+
/** A term splice is desugared by the compiler into a call to this method */
14+
@compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.exprSplice`")
15+
def exprSplice[T, QCtx <: QuoteContext](x: QCtx ?=> Expr[T]): T = ???
16+
17+
/** A type quote is desugared by the compiler into a call to this method */
18+
@compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.typeQuote`")
19+
def typeQuote[T <: AnyKind]: Type[T] = ???
20+
21+
/** A splice in a quoted pattern is desugared by the compiler into a call to this method */
22+
@compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.patternHole`")
23+
def patternHole[T]: T = ???
24+
25+
/** A splice of a name in a quoted pattern is desugared by wrapping getting this annotation */
26+
@compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.patternBindHole`")
27+
class patternBindHole extends Annotation
28+
29+
/** A splice of a name in a quoted pattern is that marks the definition of a type splice */
30+
@compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.patternType`")
31+
class patternType extends Annotation
32+
33+
/** A type pattern that must be aproximated from above */
34+
@compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.fromAbove`")
35+
class fromAbove extends Annotation
36+
37+
/** Artifact of pickled type splices
38+
*
39+
* During quote reification a quote `'{ ... F[$t] ... }` will be transformed into
40+
* `'{ @quoteTypeTag type T$1 = $t ... F[T$1] ... }` to have a tree for `$t`.
41+
* This artifact is removed during quote unpickling.
42+
*
43+
* See ReifyQuotes.scala and PickledQuotes.scala
44+
*/
45+
@compileTimeOnly("Illegal reference to `scala.internal.quoted.CompileTime.quoteTypeTag`")
46+
class quoteTypeTag extends Annotation
47+
48+
}

library/src/scala/internal/quoted/Unpickler.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,18 @@ import scala.quoted.{Expr, QuoteContext, Type}
66
object Unpickler {
77

88
type PickledQuote = List[String]
9-
type PickledExprArgs = Seq[Seq[Any] => ((QuoteContext ?=> Expr[Any]) | Type[_])]
10-
type PickledTypeArgs = Seq[Seq[Any] => Type[_]]
9+
type PickledArgs = Seq[Seq[Any] => Any/*(([QCtx <: QuoteContext] =>> QCtx ?=> Expr[Any]) | Type[_])*/]
1110

1211
/** Unpickle `repr` which represents a pickled `Expr` tree,
1312
* replacing splice nodes with `args`
1413
*/
15-
def unpickleExpr[T](repr: PickledQuote, args: PickledExprArgs): QuoteContext ?=> Expr[T] =
14+
def unpickleExpr[T](repr: PickledQuote, args: PickledArgs): QuoteContext ?=> Expr[T] =
1615
summon[QuoteContext].tasty.internal.unpickleExpr(repr, args).asInstanceOf[Expr[T]]
1716

1817
/** Unpickle `repr` which represents a pickled `Type` tree,
1918
* replacing splice nodes with `args`
2019
*/
21-
def unpickleType[T](repr: PickledQuote, args: PickledTypeArgs): QuoteContext ?=> Type[T] =
20+
def unpickleType[T](repr: PickledQuote, args: PickledArgs): QuoteContext ?=> Type[T] =
2221
summon[QuoteContext].tasty.internal.unpickleType(repr, args).asInstanceOf[Type[T]]
2322

2423
}

library/src/scala/quoted/QuoteContext.scala

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,32 @@ import scala.quoted.show.SyntaxHighlight
1010
*
1111
* @param tasty Typed AST API. Usage: `def f(qctx: QuoteContext) = { import qctx.tasty.{_, given _}; ... }`.
1212
*/
13-
class QuoteContext(val tasty: scala.tasty.Reflection) {
13+
class QuoteContext(val tasty: scala.tasty.Reflection) { self =>
1414

15+
/** Type of a QuoteContext profided by a splice within a quote that took this context.
16+
* It is only required if working with the reflection API.
17+
*
18+
* Usually it is infered by the quotes an splices typing. But sometimes it is necessary
19+
* to explicitly state that a context is nested as in the following example:
20+
*
21+
* ```scala
22+
* def run(using qctx: QuoteContext)(tree: qctx.tasty.Tree): Unit =
23+
* def nested()(using qctx.NestedContext): Expr[Int] = '{ ${ makeExpr(tree) } + 1 }
24+
* '{ ${ nested() } + 2 }
25+
* def makeExpr(using qctx: QuoteContext)(tree: qctx.tasty.Tree): Expr[Int] = ???
26+
* ```
27+
*/
28+
type NestedContext = QuoteContext {
29+
val tasty: self.tasty.type
30+
}
31+
32+
/** Show the fully elaborated source code representation of an expression */
1533
def show(expr: Expr[_], syntaxHighlight: SyntaxHighlight): String = {
1634
import tasty.{_, given _}
1735
expr.unseal.showWith(syntaxHighlight)
1836
}
1937

38+
/** Show the fully elaborated source code representation of a type */
2039
def show(tpe: Type[_], syntaxHighlight: SyntaxHighlight): String = {
2140
import tasty.{_, given _}
2241
tpe.unseal.showWith(syntaxHighlight)

library/src/scala/tasty/reflect/CompilerInterface.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,12 @@ trait CompilerInterface {
125125
/** Unpickle `repr` which represents a pickled `Expr` tree,
126126
* replacing splice nodes with `args`
127127
*/
128-
def unpickleExpr(repr: Unpickler.PickledQuote, args: Unpickler.PickledExprArgs): scala.quoted.Expr[_]
128+
def unpickleExpr(repr: Unpickler.PickledQuote, args: Unpickler.PickledArgs): scala.quoted.Expr[_]
129129

130130
/** Unpickle `repr` which represents a pickled `Type` tree,
131131
* replacing splice nodes with `args`
132132
*/
133-
def unpickleType(repr: Unpickler.PickledQuote, args: Unpickler.PickledTypeArgs): scala.quoted.Type[_]
133+
def unpickleType(repr: Unpickler.PickledQuote, args: Unpickler.PickledArgs): scala.quoted.Type[_]
134134

135135

136136
/////////////

tests/pos/i8045.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import scala.quoted._
2+
object Test
3+
def run(using qctx: QuoteContext)(tree: qctx.tasty.Tree): Unit =
4+
'{ ${ makeExpr(tree) } + 1 }
5+
def makeExpr(using qctx: QuoteContext)(tree: qctx.tasty.Tree): Expr[Int] = ???

tests/pos/i8045b.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import scala.quoted._
2+
object Test
3+
def run(using qctx: QuoteContext)(tree: qctx.tasty.Tree): Unit =
4+
def nested()(using qctx.NestedContext): Expr[Int] =
5+
'{ ${ makeExpr(tree) } + 1 }
6+
'{ ${ nested() } + 2 }
7+
8+
def makeExpr(using qctx: QuoteContext)(tree: qctx.tasty.Tree): Expr[Int] = ???
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] = scala.internal.quoted.CompileTime.exprQuote[scala.Int](4).apply(using qctx)
3-
((qctx1_$1: scala.quoted.QuoteContext) ?=> a).apply(using qctx)
3+
((qctx1_$1: qctx.NestedContext) ?=> a).asInstanceOf[scala.ContextFunction1[scala.quoted.QuoteContext, scala.quoted.Expr[scala.Int]]].apply(using qctx)
44
})
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] = scala.internal.quoted.CompileTime.exprQuote[scala.Int](4).apply(using qctx)
3-
((qctx2: scala.quoted.QuoteContext) ?=> ((qctx1_$1: scala.quoted.QuoteContext) ?=> a).apply(using qctx2)).apply(using qctx)
3+
((qctx2: scala.quoted.QuoteContext) ?=> ((qctx1_$1: qctx2.NestedContext) ?=> a).asInstanceOf[scala.ContextFunction1[scala.quoted.QuoteContext, scala.quoted.Expr[scala.Int]]].apply(using qctx2)).apply(using qctx)
44
})

0 commit comments

Comments
 (0)