diff --git a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala index 68e06773642b..527c15414365 100644 --- a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala +++ b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala @@ -46,7 +46,7 @@ object PickledQuotes { case value: Class[_] => ref(defn.Predef_classOf).appliedToType(classToType(value)) case value => Literal(Constant(value)) } - case expr: TastyTreeExpr[Tree] @unchecked => expr.tree + case expr: TastyTreeExpr[Tree] @unchecked => healOwner(expr.tree) case expr: FunctionAppliedTo[_, _] => functionAppliedTo(quotedExprToTree(expr.f), quotedExprToTree(expr.x)) } @@ -55,7 +55,7 @@ object PickledQuotes { def quotedTypeToTree(expr: quoted.Type[_])(implicit ctx: Context): Tree = expr match { case expr: TastyType[_] => unpickleType(expr) case expr: TaggedType[_] => classTagToTypeTree(expr.ct) - case expr: TreeType[Tree] @unchecked => expr.typeTree + case expr: TreeType[Tree] @unchecked => healOwner(expr.typeTree) } /** Unpickle the tree contained in the TastyExpr */ @@ -170,4 +170,21 @@ object PickledQuotes { } } else ctx.getClassIfDefined(clazz.getCanonicalName).typeRef } + + /** Make sure that the owner of this tree is `ctx.owner` */ + private def healOwner(tree: Tree)(implicit ctx: Context): Tree = { + val getCurrentOwner = new TreeAccumulator[Option[Symbol]] { + def apply(x: Option[Symbol], tree: tpd.Tree)(implicit ctx: Context): Option[Symbol] = { + if (x.isDefined) x + else tree match { + case tree: DefTree => Some(tree.symbol.owner) + case _ => foldOver(x, tree) + } + } + } + getCurrentOwner(None, tree) match { + case Some(owner) if owner != ctx.owner => tree.changeOwner(owner, ctx.owner) + case _ => tree + } + } } diff --git a/compiler/test/dotc/run-test-pickling.blacklist b/compiler/test/dotc/run-test-pickling.blacklist index 7dc319af5a50..dbfef1b230e1 100644 --- a/compiler/test/dotc/run-test-pickling.blacklist +++ b/compiler/test/dotc/run-test-pickling.blacklist @@ -38,6 +38,7 @@ mixins1 outerPatternMatch paramForwarding_separate quote-and-splice +quote-change-owner quote-force quote-indexed-map-by-name quote-sep-comp diff --git a/tests/run/quote-change-owner.check b/tests/run/quote-change-owner.check new file mode 100644 index 000000000000..5716ca5987cb --- /dev/null +++ b/tests/run/quote-change-owner.check @@ -0,0 +1 @@ +bar diff --git a/tests/run/quote-change-owner/Macro_1.scala b/tests/run/quote-change-owner/Macro_1.scala new file mode 100644 index 000000000000..7ae01816db48 --- /dev/null +++ b/tests/run/quote-change-owner/Macro_1.scala @@ -0,0 +1,8 @@ +import scala.quoted._ +object Macros { + inline def assert2(expr: => Boolean): Unit = ~ assertImpl('(expr)) + def assertImpl(expr: Expr[Boolean]) = '{ + def foo(): Unit = ~expr + foo() + } +} diff --git a/tests/run/quote-change-owner/Test_2.scala b/tests/run/quote-change-owner/Test_2.scala new file mode 100644 index 000000000000..17730efe0dda --- /dev/null +++ b/tests/run/quote-change-owner/Test_2.scala @@ -0,0 +1,12 @@ +import Macros._ +object Test { + def main(args: Array[String]): Unit = { + assert2 { + def bar(): Boolean = { + println("bar") + false + } + bar() + } + } +}