Skip to content

Commit 6a50483

Browse files
committed
fixed changeOwner to work for case, when tree is assembeled from parts of trees with different owners.
1 parent c5dfa75 commit 6a50483

File tree

3 files changed

+42
-17
lines changed

3 files changed

+42
-17
lines changed

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

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -799,13 +799,29 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
799799
* owner to `to`, and continue until a non-weak owner is reached.
800800
*/
801801
def changeOwner(from: Symbol, to: Symbol)(using Context): ThisTree = {
802-
@tailrec def loop(from: Symbol, froms: List[Symbol], tos: List[Symbol]): ThisTree =
803-
if (from.isWeakOwner && !from.owner.isClass)
804-
loop(from.owner, from :: froms, to :: tos)
805-
else
806-
//println(i"change owner ${from :: froms}%, % ==> $tos of $tree")
807-
TreeTypeMap(oldOwners = from :: froms, newOwners = tos).apply(tree)
808-
if (from == to) tree else loop(from, Nil, to :: Nil)
802+
changeOwners(List(from),to)
803+
}
804+
805+
/** Change owner from all `froms` to `to`. If `from` is a weak owner, also change its
806+
* owner to `to`, and continue until a non-weak owner is reached.
807+
*/
808+
def changeOwners(froms: List[Symbol], to: Symbol)(using Context): ThisTree = {
809+
@tailrec def loop(froms: List[Symbol], processedFroms: List[Symbol], tos: List[Symbol]): ThisTree =
810+
froms match
811+
case from::rest =>
812+
if (from == to)
813+
loop(rest, processedFroms, tos)
814+
else
815+
if (from.isWeakOwner && !from.owner.isClass)
816+
loop(from.owner::rest, from :: processedFroms, to :: tos)
817+
else
818+
loop(rest, from::processedFroms, to :: tos)
819+
case Nil =>
820+
if (processedFroms.isEmpty)
821+
tree
822+
else
823+
TreeTypeMap(oldOwners = processedFroms, newOwners = tos).apply(tree)
824+
loop(froms, Nil, Nil)
809825
}
810826

811827
/**

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dotty.tools.dotc.quoted
22

33
import dotty.tools.dotc
44
import dotty.tools.dotc.ast.tpd
5+
import dotty.tools.dotc.ast.tpd.TreeOps
56
import dotty.tools.dotc.ast.untpd
67
import dotty.tools.dotc.core.Annotations
78
import dotty.tools.dotc.core.Contexts._
@@ -742,6 +743,8 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, scala.intern
742743
def unapply(tree: Block): Option[(List[ValDef], Term)] = tree match {
743744
case Block((ddef @ DefDef(_, _, params :: Nil, _, Some(body))) :: Nil, Closure(meth, _))
744745
if ddef.symbol == meth.symbol =>
746+
//val cleanParams = params.map(_.changeOwner(meth.symbol,ctx.owner))
747+
//val cleanBody = body.changeOwner(meth.symbol,ctx.owner)
745748
Some((params, body))
746749
case _ => None
747750
}

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

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,30 @@ import dotty.tools.dotc.core.Symbols._
99
object QuoteUtils:
1010
import tpd._
1111

12-
/** Get the owner of a tree if it has one */
13-
def treeOwner(tree: Tree)(using Context): Option[Symbol] = {
14-
val getCurrentOwner = new TreeAccumulator[Option[Symbol]] {
15-
def apply(x: Option[Symbol], tree: tpd.Tree)(using Context): Option[Symbol] =
16-
if (x.isDefined) x
17-
else tree match {
18-
case tree: DefTree => Some(tree.symbol.owner)
19-
case _ => foldOver(x, tree)
12+
/** Get the list of owners of a tree if it has one */
13+
def treeOwners(tree: Tree)(using Context): List[Symbol] = {
14+
val getOwners = new TreeAccumulator[Map[Int,Symbol]] {
15+
def apply(x: Map[Int,Symbol], tree: tpd.Tree)(using Context): Map[Int,Symbol] =
16+
tree match {
17+
case tree: DefTree => val owner = tree.symbol.owner
18+
x.updated(owner.id, owner)
19+
case _ => foldOver(x,tree)
2020
}
2121
}
22-
getCurrentOwner(None, tree)
22+
getOwners(Map.empty,tree).values.toList
2323
}
2424

25+
2526
/** Changes the owner of the tree based on the current owner of the tree */
2627
def changeOwnerOfTree(tree: Tree, owner: Symbol)(using Context): Tree = {
28+
tree.changeOwners(treeOwners(tree), owner)
29+
/*
2730
treeOwner(tree) match
2831
case Some(oldOwner) if oldOwner != owner => tree.changeOwner(oldOwner, owner)
29-
case _ => tree
32+
case _ =>
33+
println(s"tree without owner: $tree")
34+
tree
35+
*/
3036
}
3137

3238
end QuoteUtils

0 commit comments

Comments
 (0)