From 96bfb69c933148ad0561e589a444fab1308d7951 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 8 Feb 2023 11:58:53 +0100 Subject: [PATCH] Handle pickled forward references in pickled expressions To compute forward references it was assumed that the owner of that symbol can be found in the TASTy. This is not always the case with TASTy expressions of pickled quotes. The owner might be outside the quote, in this case the context already has the owner of the referenced symbol. These are local symbols defined at the top-level of the TASTy. Fixes #16843 --- .../tools/dotc/core/tasty/TreeUnpickler.scala | 6 +++++- tests/pos-macros/i16843a/Macro_1.scala | 13 +++++++++++++ tests/pos-macros/i16843a/Test_2.scala | 1 + tests/pos-macros/i16843b/Macro_1.scala | 18 ++++++++++++++++++ tests/pos-macros/i16843b/Test_2.scala | 1 + 5 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/pos-macros/i16843a/Macro_1.scala create mode 100644 tests/pos-macros/i16843a/Test_2.scala create mode 100644 tests/pos-macros/i16843b/Macro_1.scala create mode 100644 tests/pos-macros/i16843b/Test_2.scala diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 91290b4ddd41..dfe04dbe6d2b 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -74,6 +74,9 @@ class TreeUnpickler(reader: TastyReader, */ private val typeAtAddr = new mutable.HashMap[Addr, Type] + /** If this is a pickled quote, the owner of the quote, otherwise NoSymbol. */ + private var rootOwner: Symbol = NoSymbol + /** The root symbol denotation which are defined by the Tasty file associated with this * TreeUnpickler. Set by `enterTopLevel`. */ @@ -106,6 +109,7 @@ class TreeUnpickler(reader: TastyReader, /** The unpickled trees */ def unpickle(mode: UnpickleMode)(using Context): List[Tree] = { + if mode != UnpickleMode.TopLevel then rootOwner = ctx.owner assert(roots != null, "unpickle without previous enterTopLevel") val rdr = new TreeReader(reader) mode match { @@ -1635,7 +1639,7 @@ class TreeUnpickler(reader: TastyReader, pickling.println(i"no owner for $addr among $cs%, %") throw ex } - try search(children, NoSymbol) + try search(children, rootOwner) catch { case ex: TreeWithoutOwner => pickling.println(s"ownerTree = $ownerTree") diff --git a/tests/pos-macros/i16843a/Macro_1.scala b/tests/pos-macros/i16843a/Macro_1.scala new file mode 100644 index 000000000000..98c1505910e6 --- /dev/null +++ b/tests/pos-macros/i16843a/Macro_1.scala @@ -0,0 +1,13 @@ +import scala.quoted.* + +case class Foo(x: Int) + +inline def foo = ${ fooImpl } + +def fooImpl(using Quotes) = + val tmp = '{ + 1 match + case x @ (y: Int) => 0 + } + + '{} diff --git a/tests/pos-macros/i16843a/Test_2.scala b/tests/pos-macros/i16843a/Test_2.scala new file mode 100644 index 000000000000..25406428d0cf --- /dev/null +++ b/tests/pos-macros/i16843a/Test_2.scala @@ -0,0 +1 @@ +val x = foo diff --git a/tests/pos-macros/i16843b/Macro_1.scala b/tests/pos-macros/i16843b/Macro_1.scala new file mode 100644 index 000000000000..631bde56f1f1 --- /dev/null +++ b/tests/pos-macros/i16843b/Macro_1.scala @@ -0,0 +1,18 @@ +import scala.quoted.* + +inline def foo: Int = ${ fooImpl } + +def fooImpl(using Quotes): Expr[Int] = + '{ + val b = ${ + val a = '{ + (1: Int) match + case x @ (y: Int) => 0 + } + a + } + + (1: Int) match + case x @ (y: Int) => 0 + } + diff --git a/tests/pos-macros/i16843b/Test_2.scala b/tests/pos-macros/i16843b/Test_2.scala new file mode 100644 index 000000000000..54c769c9618f --- /dev/null +++ b/tests/pos-macros/i16843b/Test_2.scala @@ -0,0 +1 @@ +def test = foo