Skip to content

Commit 5660b89

Browse files
committed
Change owners only once for nested unpickled quotes
1 parent d985903 commit 5660b89

File tree

4 files changed

+33
-16
lines changed

4 files changed

+33
-16
lines changed

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

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import scala.quoted.Exprs._
1919

2020
import scala.reflect.ClassTag
2121

22+
import scala.collection.mutable
23+
2224
object PickledQuotes {
2325
import tpd._
2426

@@ -34,43 +36,58 @@ object PickledQuotes {
3436
}
3537

3638
/** Transform the expression into its fully spliced Tree */
37-
def quotedExprToTree[T](expr: quoted.Expr[T])(implicit ctx: Context): Tree = expr match {
38-
case expr: TastyExpr[_] => unpickleExpr(expr)
39+
def quotedExprToTree[T](expr: quoted.Expr[T], nested: Boolean)(implicit ctx: Context): Tree = expr match {
40+
case expr: TastyExpr[_] => unpickleExpr(expr, nested)
3941
case expr: LiftedExpr[T] =>
4042
expr.value match {
4143
case value: Class[_] => ref(defn.Predef_classOf).appliedToType(classToType(value))
42-
case value=> Literal(Constant(value))
44+
case value => Literal(Constant(value))
4345
}
4446
case expr: TreeExpr[Tree] @unchecked => expr.tree
4547
case expr: FunctionAppliedTo[_, _] =>
46-
functionAppliedTo(quotedExprToTree(expr.f), quotedExprToTree(expr.x))
48+
functionAppliedTo(quotedExprToTree(expr.f, nested), quotedExprToTree(expr.x, nested))
4749
}
4850

4951
/** Transform the expression into its fully spliced TypeTree */
50-
def quotedTypeToTree(expr: quoted.Type[_])(implicit ctx: Context): Tree = expr match {
51-
case expr: TastyType[_] => unpickleType(expr)
52+
def quotedTypeToTree(expr: quoted.Type[_], nested: Boolean)(implicit ctx: Context): Tree = expr match {
53+
case expr: TastyType[_] => unpickleType(expr, nested)
5254
case expr: TaggedType[_] => classTagToTypeTree(expr.ct)
5355
case expr: TreeType[Tree] @unchecked => expr.tree
5456
}
5557

5658
/** Unpickle the tree contained in the TastyExpr */
57-
private def unpickleExpr(expr: TastyExpr[_])(implicit ctx: Context): Tree = {
59+
private def unpickleExpr(expr: TastyExpr[_], nested: Boolean)(implicit ctx: Context): Tree = {
5860
val tastyBytes = TastyString.unpickle(expr.tasty)
5961
val unpickled = unpickle(tastyBytes, expr.args)
6062
unpickled match {
6163
case PackageDef(_, (vdef: ValDef) :: Nil) =>
62-
vdef.rhs.changeOwner(vdef.symbol, ctx.owner)
64+
changeQuoteOwners(vdef.rhs, nested)
6365
}
6466
}
6567

6668
/** Unpickle the tree contained in the TastyType */
67-
private def unpickleType(ttpe: TastyType[_])(implicit ctx: Context): Tree = {
69+
private def unpickleType(ttpe: TastyType[_], nested: Boolean)(implicit ctx: Context): Tree = {
6870
val tastyBytes = TastyString.unpickle(ttpe.tasty)
6971
val unpickled = unpickle(tastyBytes, ttpe.args)
7072
unpickled match {
7173
case PackageDef(_, (vdef: ValDef) :: Nil) =>
72-
vdef.rhs.asInstanceOf[TypeApply].args.head
73-
.changeOwner(vdef.symbol, ctx.owner)
74+
changeQuoteOwners(vdef.rhs.asInstanceOf[TypeApply].args.head, nested)
75+
}
76+
}
77+
78+
private def changeQuoteOwners(tree: Tree, nested: Boolean)(implicit ctx: Context): Tree = {
79+
if (nested) tree
80+
else {
81+
val set = mutable.HashSet.empty[Symbol]
82+
new TreeTraverser {
83+
override def traverse(tree: tpd.Tree)(implicit ctx: Context): Unit = {
84+
if (tree.symbol.exists && tree.symbol.owner.name == "$quote".toTermName)
85+
set += tree.symbol.owner
86+
traverseChildren(tree)
87+
}
88+
}.traverse(tree)
89+
val owners = set.toList
90+
new TreeTypeMap(oldOwners = owners, newOwners = owners.map(_ => ctx.owner)).apply(tree)
7491
}
7592
}
7693

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,12 +1145,12 @@ class TreeUnpickler(reader: TastyReader,
11451145
val quotedType =
11461146
if (reifiedArgs.isEmpty) splice.asInstanceOf[quoted.Type[_]]
11471147
else splice.asInstanceOf[Seq[Any] => quoted.Type[_]](reifiedArgs)
1148-
PickledQuotes.quotedTypeToTree(quotedType)
1148+
PickledQuotes.quotedTypeToTree(quotedType, nested = true)
11491149
} else {
11501150
val quotedExpr =
11511151
if (reifiedArgs.isEmpty) splice.asInstanceOf[quoted.Expr[_]]
11521152
else splice.asInstanceOf[Seq[Any] => quoted.Expr[_]](reifiedArgs)
1153-
PickledQuotes.quotedExprToTree(quotedExpr)
1153+
PickledQuotes.quotedExprToTree(quotedExpr, nested = true)
11541154
}
11551155
}
11561156

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class ExprCompiler(directory: AbstractFile) extends Compiler {
6161
case exprUnit: ExprCompilationUnit =>
6262
val tree =
6363
if (putInClass) inClass(exprUnit.expr)
64-
else PickledQuotes.quotedExprToTree(exprUnit.expr)
64+
else PickledQuotes.quotedExprToTree(exprUnit.expr, nested = false)
6565
val source = new SourceFile("", Seq())
6666
CompilationUnit.mkCompilationUnit(source, tree, forceTrees = true)
6767
}
@@ -80,7 +80,7 @@ class ExprCompiler(directory: AbstractFile) extends Compiler {
8080
cls.enter(ctx.newDefaultConstructor(cls), EmptyScope)
8181
val meth = ctx.newSymbol(cls, nme.apply, Method, ExprType(defn.AnyType), coord = pos).entered
8282

83-
val quoted = PickledQuotes.quotedExprToTree(expr)(ctx.withOwner(meth))
83+
val quoted = PickledQuotes.quotedExprToTree(expr, nested = false)(ctx.withOwner(meth))
8484

8585
val run = DefDef(meth, quoted)
8686
val classTree = ClassDef(cls, DefDef(cls.primaryConstructor.asTerm), run :: Nil)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ object Splicer {
3939
val liftedArgs = getLiftedArgs(call, bindings)
4040
val interpreter = new Interpreter(pos)
4141
val interpreted = interpreter.interpretCallToSymbol[Seq[Any] => Object](call.symbol)
42-
interpreted.flatMap(lambda => evaluateLambda(lambda, liftedArgs, pos)).fold(tree)(PickledQuotes.quotedExprToTree)
42+
interpreted.flatMap(lambda => evaluateLambda(lambda, liftedArgs, pos)).fold(tree)(PickledQuotes.quotedExprToTree(_, nested = false))
4343
}
4444

4545
/** Given the inline code and bindings, compute the lifted arguments that will be used to execute the macro

0 commit comments

Comments
 (0)