Skip to content

Commit 42d5c26

Browse files
Merge pull request scala#10238 from dotty-staging/encode-unpickle-call-directly-on-context
Encode unpickle call directly on context
2 parents 3e30786 + d35a5d7 commit 42d5c26

File tree

5 files changed

+34
-26
lines changed

5 files changed

+34
-26
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,7 @@ class Definitions {
795795
@tu lazy val QuotedExprModule: Symbol = QuotedExprClass.companionModule
796796

797797
@tu lazy val QuoteContextClass: ClassSymbol = requiredClass("scala.quoted.QuoteContext")
798+
@tu lazy val QuoteContextInternalClass: ClassSymbol = requiredClass("scala.internal.quoted.QuoteContextInternal")
798799

799800
@tu lazy val LiftableModule: Symbol = requiredModule("scala.quoted.Liftable")
800801
@tu lazy val LiftableModule_BooleanLiftable: Symbol = LiftableModule.requiredMethod("BooleanLiftable")
@@ -837,8 +838,6 @@ class Definitions {
837838
@tu lazy val TastyReflectionClass: ClassSymbol = requiredClass("scala.tasty.Reflection")
838839

839840
@tu lazy val PickledQuote_make: Symbol = requiredMethod("scala.internal.quoted.PickledQuote.make")
840-
@tu lazy val PickledQuote_unpickleExpr: Symbol = requiredMethod("scala.internal.quoted.PickledQuote.unpickleExpr")
841-
@tu lazy val PickledQuote_unpickleType: Symbol = requiredMethod("scala.internal.quoted.PickledQuote.unpickleType")
842841

843842
@tu lazy val EqlClass: ClassSymbol = requiredClass("scala.Eql")
844843
def Eql_eqlAny(using Context): TermSymbol = EqlClass.companionModule.requiredMethod(nme.eqlAny)

compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,13 +2631,13 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, scala.intern
26312631

26322632
end reflect
26332633

2634-
def unpickleExpr(pickledQuote: PickledQuote): scala.quoted.Expr[Any] =
2634+
def unpickleExpr[T](pickledQuote: PickledQuote): scala.quoted.Expr[T] =
26352635
val tree = PickledQuotes.unpickleTerm(pickledQuote)(using reflect.rootContext)
2636-
new scala.internal.quoted.Expr(tree, hash)
2636+
new scala.internal.quoted.Expr(tree, hash).asInstanceOf[scala.quoted.Expr[T]]
26372637

2638-
def unpickleType(pickledQuote: PickledQuote): scala.quoted.Type[?] =
2638+
def unpickleType[T <: AnyKind](pickledQuote: PickledQuote): scala.quoted.Type[T] =
26392639
val tree = PickledQuotes.unpickleTypeTree(pickledQuote)(using reflect.rootContext)
2640-
new scala.internal.quoted.Type(tree, hash)
2640+
new scala.internal.quoted.Type(tree, hash).asInstanceOf[scala.quoted.Type[T]]
26412641

26422642
def exprMatch(scrutinee: scala.quoted.Expr[Any], pattern: scala.quoted.Expr[Any]): Option[Tuple] =
26432643
treeMatch(scrutinee.unseal(using this), pattern.unseal(using this))

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

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,9 @@ class ReifyQuotes extends MacroTransform {
155155
*/
156156
def pickleAsLiteral(lit: Literal) = {
157157
val exprType = defn.QuotedExprClass.typeRef.appliedTo(body.tpe)
158-
val tpe = MethodType(defn.QuoteContextClass.typeRef :: Nil, exprType)
159-
val meth = newSymbol(ctx.owner, UniqueName.fresh(nme.ANON_FUN), Synthetic | Method, tpe)
160-
def mkConst(tss: List[List[Tree]]) = {
161-
val reflect = tss.head.head.select("reflect".toTermName)
158+
val lambdaTpe = MethodType(defn.QuoteContextClass.typeRef :: Nil, exprType)
159+
def mkConst(ts: List[Tree]) = {
160+
val reflect = ts.head.select("reflect".toTermName)
162161
val typeName = body.tpe.typeSymbol.name
163162
val literalValue =
164163
if lit.const.tag == Constants.NullTag || lit.const.tag == Constants.UnitTag then Nil
@@ -167,7 +166,7 @@ class ReifyQuotes extends MacroTransform {
167166
val literal = reflect.select("Literal".toTermName).select(nme.apply).appliedTo(constant)
168167
reflect.select("TreeMethods".toTermName).select("asExpr".toTermName).appliedTo(literal).asInstance(exprType)
169168
}
170-
Closure(meth, mkConst).withSpan(body.span)
169+
Lambda(lambdaTpe, mkConst).withSpan(body.span)
171170
}
172171

173172
def pickleAsValue(lit: Literal) = {
@@ -190,13 +189,30 @@ class ReifyQuotes extends MacroTransform {
190189
}
191190
}
192191

192+
/** Encode quote using QuoteContextInternal.{unpickleExpr, unpickleType}
193+
*
194+
* Generate the code
195+
* ```scala
196+
* qctx => qctx.asInstanceOf[QuoteContextInternal].<unpickleExpr|unpickleType>[<type>](
197+
* <pickledQuote>
198+
* )
199+
* ```
200+
* this closure is always applied directly to the actual context and the BetaReduce phase removes it.
201+
*/
193202
def pickleAsTasty() = {
194-
val unpickleMeth = if isType then defn.PickledQuote_unpickleType else defn.PickledQuote_unpickleExpr
195203
val pickledQuoteStrings = liftList(PickledQuotes.pickleQuote(body).map(x => Literal(Constant(x))), defn.StringType)
196204
// TODO: generate an instance of PickledSplices directly instead of passing through a List
197205
val splicesList = liftList(splices, defn.FunctionType(1).appliedTo(defn.SeqType.appliedTo(defn.AnyType), defn.AnyType))
198206
val pickledQuote = ref(defn.PickledQuote_make).appliedTo(pickledQuoteStrings, splicesList)
199-
ref(unpickleMeth).appliedToType(originalTp).appliedTo(pickledQuote)
207+
val quoteClass = if isType then defn.QuotedTypeClass else defn.QuotedExprClass
208+
val quotedType = quoteClass.typeRef.appliedTo(originalTp)
209+
val lambdaTpe = MethodType(defn.QuoteContextClass.typeRef :: Nil, quotedType)
210+
def callUnpickle(ts: List[Tree]) = {
211+
val qctx = ts.head.asInstance(defn.QuoteContextInternalClass.typeRef)
212+
val unpickleMethName = if isType then "unpickleType" else "unpickleExpr"
213+
qctx.select(unpickleMethName.toTermName).appliedToType(originalTp).appliedTo(pickledQuote)
214+
}
215+
Lambda(lambdaTpe, callUnpickle).withSpan(body.span)
200216
}
201217

202218
/** Encode quote using Reflection.TypeRepr.typeConstructorOf
@@ -212,14 +228,13 @@ class ReifyQuotes extends MacroTransform {
212228
def taggedType() =
213229
val typeType = defn.QuotedTypeClass.typeRef.appliedTo(body.tpe)
214230
val classTree = TypeApply(ref(defn.Predef_classOf.termRef), body :: Nil)
215-
val tpe = MethodType(defn.QuoteContextClass.typeRef :: Nil, typeType)
216-
val meth = newSymbol(ctx.owner, UniqueName.fresh(nme.ANON_FUN), Synthetic | Method, tpe)
217-
def mkConst(tss: List[List[Tree]]) = {
218-
val reflect = tss.head.head.select("reflect".toTermName)
231+
val lambdaTpe = MethodType(defn.QuoteContextClass.typeRef :: Nil, typeType)
232+
def callTypeConstructorOf(ts: List[Tree]) = {
233+
val reflect = ts.head.select("reflect".toTermName)
219234
val typeRepr = reflect.select("TypeRepr".toTermName).select("typeConstructorOf".toTermName).appliedTo(classTree)
220235
reflect.select("TypeReprMethods".toTermName).select("asType".toTermName).appliedTo(typeRepr).asInstance(typeType)
221236
}
222-
Closure(meth, mkConst).withSpan(body.span)
237+
Lambda(lambdaTpe, callTypeConstructorOf).withSpan(body.span)
223238

224239
if (isType) {
225240
if (splices.isEmpty && body.symbol.isPrimitiveValueClass) taggedType()

library/src/scala/internal/quoted/PickledQuote.scala

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,6 @@ trait PickledQuote:
1616

1717
object PickledQuote:
1818

19-
def unpickleExpr[T](pickledQuote: PickledQuote): QuoteContext ?=> Expr[T] =
20-
qctx.asInstanceOf[QuoteContextInternal].unpickleExpr(pickledQuote).asInstanceOf[Expr[T]]
21-
22-
def unpickleType[T](pickledQuote: PickledQuote): QuoteContext ?=> Type[T] =
23-
qctx.asInstanceOf[QuoteContextInternal].unpickleType(pickledQuote).asInstanceOf[Type[T]]
24-
2519
/** Create an instance of PickledExpr from encoded tasty and sequence of labmdas to fill holes
2620
*
2721
* @param pickled: Bytes of tasty encoded using TastyString.pickle

library/src/scala/internal/quoted/QuoteContextInternal.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ trait QuoteContextInternal { self: scala.quoted.QuoteContext =>
1010
/** Unpickle `repr` which represents a pickled `Expr` tree,
1111
* replacing splice nodes with `holes`
1212
*/
13-
def unpickleExpr(pickledQuote: PickledQuote): scala.quoted.Expr[Any]
13+
def unpickleExpr[T](pickledQuote: PickledQuote): scala.quoted.Expr[T]
1414

1515
/** Unpickle `repr` which represents a pickled `Type` tree,
1616
* replacing splice nodes with `holes`
1717
*/
18-
def unpickleType(pickledQuote: PickledQuote): scala.quoted.Type[?]
18+
def unpickleType[T <: AnyKind](pickledQuote: PickledQuote): scala.quoted.Type[T]
1919

2020
/** Pattern matches the scrutinee against the pattern and returns a tuple
2121
* with the matched holes if successful.

0 commit comments

Comments
 (0)