From fd34d997ec5615644792794ebb6443d259156df7 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 17 Sep 2021 09:41:11 +0200 Subject: [PATCH 1/3] Set the correct owner when quote making inlinable Fixes #13546 --- .../dotty/tools/dotc/typer/QuotesAndSplices.scala | 6 +++++- tests/pos-macros/i13546/Macros_1.scala | 13 +++++++++++++ tests/pos-macros/i13546/Test_2.scala | 5 +++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/pos-macros/i13546/Macros_1.scala create mode 100644 tests/pos-macros/i13546/Test_2.scala diff --git a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala index 0d9186a0fb5f..8b1ac0aeb9da 100644 --- a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala +++ b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala @@ -70,7 +70,11 @@ trait QuotesAndSplices { } private def makeInlineable(tree: Tree)(using Context): Tree = - PrepareInlineable.makeInlineable(tree) + def quoteOwner(sym: Symbol): Symbol = + if sym.owner.isClass then sym else quoteOwner(sym.owner) + inContext(ctx.withOwner(quoteOwner(ctx.owner))) { + PrepareInlineable.makeInlineable(tree) + } /** Translate `${ t: Expr[T] }` into expression `t.splice` while tracking the quotation level in the context */ def typedSplice(tree: untpd.Splice, pt: Type)(using Context): Tree = { diff --git a/tests/pos-macros/i13546/Macros_1.scala b/tests/pos-macros/i13546/Macros_1.scala new file mode 100644 index 000000000000..7e90476c5f73 --- /dev/null +++ b/tests/pos-macros/i13546/Macros_1.scala @@ -0,0 +1,13 @@ +package mylib +import scala.quoted.* + +object Main: + protected def foo: Unit = {} + inline def fooCaller: Unit = + def f = foo + foo + inline def fooCallerM: Unit = ${ fooMacro } + def fooMacro(using Quotes): Expr[Unit] = + '{ foo } + val fooExpr = '{ foo } + '{ $fooExpr } diff --git a/tests/pos-macros/i13546/Test_2.scala b/tests/pos-macros/i13546/Test_2.scala new file mode 100644 index 000000000000..386f1b3bd8f5 --- /dev/null +++ b/tests/pos-macros/i13546/Test_2.scala @@ -0,0 +1,5 @@ +import mylib.Main + +object Test: + Main.fooCaller + Main.fooCallerM From 0b072d6b7df6d9c65d6ffce779c3417df42b47bd Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 8 Oct 2021 12:04:39 +0200 Subject: [PATCH 2/3] Do not make pattern quotes inlinable --- .../tools/dotc/typer/QuotesAndSplices.scala | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala index 8b1ac0aeb9da..823b3482e34b 100644 --- a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala +++ b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala @@ -56,17 +56,17 @@ trait QuotesAndSplices { else if !qctx.tpe.isStable then report.error(em"Quotes require stable Quotes, but found non stable $qctx", qctx.srcPos) - val tree1 = - if ctx.mode.is(Mode.Pattern) then - typedQuotePattern(tree, pt, qctx) - else if tree.quoted.isType then - val msg = em"Consider using canonical type constructor scala.quoted.Type.of[${tree.quoted}] instead" - if sourceVersion.isAtLeast(`future-migration`) then report.error(msg, tree.srcPos) - else report.warning(msg, tree.srcPos) - typedTypeApply(untpd.TypeApply(untpd.ref(defn.QuotedTypeModule_of.termRef), tree.quoted :: Nil), pt)(using quoteContext).select(nme.apply).appliedTo(qctx) - else - typedApply(untpd.Apply(untpd.ref(defn.QuotedRuntime_exprQuote.termRef), tree.quoted), pt)(using pushQuotes(qctx)).select(nme.apply).appliedTo(qctx) - makeInlineable(tree1.withSpan(tree.span)) + if ctx.mode.is(Mode.Pattern) then + typedQuotePattern(tree, pt, qctx).withSpan(tree.span) + else if tree.quoted.isType then + val msg = em"Consider using canonical type constructor scala.quoted.Type.of[${tree.quoted}] instead" + if sourceVersion.isAtLeast(`future-migration`) then report.error(msg, tree.srcPos) + else report.warning(msg, tree.srcPos) + val typeOfTree = untpd.TypeApply(untpd.ref(defn.QuotedTypeModule_of.termRef), tree.quoted :: Nil).withSpan(tree.span) + makeInlineable(typedTypeApply(typeOfTree, pt)(using quoteContext).select(nme.apply).appliedTo(qctx).withSpan(tree.span)) + else + val exprQuoteTree = untpd.Apply(untpd.ref(defn.QuotedRuntime_exprQuote.termRef), tree.quoted) + makeInlineable(typedApply(exprQuoteTree, pt)(using pushQuotes(qctx)).select(nme.apply).appliedTo(qctx).withSpan(tree.span)) } private def makeInlineable(tree: Tree)(using Context): Tree = From 09cb92556542e60b75c8b9ea6402453f0df897d1 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 11 Oct 2021 15:29:54 +0200 Subject: [PATCH 3/3] Add skipLocalOwners --- compiler/src/dotty/tools/dotc/core/SymDenotations.scala | 5 +++++ compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 0c5aca3c2244..7f47f1696cd6 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1110,6 +1110,11 @@ object SymDenotations { enclClass(symbol, false) } + /** Skips symbol that are not owned by a class */ + def skipLocalOwners(using Context): Symbol = + if symbol.owner.isClass then symbol + else symbol.owner.skipLocalOwners + /** A class that in source code would be lexically enclosing */ final def lexicallyEnclosingClass(using Context): Symbol = if (!exists || isClass) symbol else owner.lexicallyEnclosingClass diff --git a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala index 823b3482e34b..86cd7e5f24f3 100644 --- a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala +++ b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala @@ -70,9 +70,7 @@ trait QuotesAndSplices { } private def makeInlineable(tree: Tree)(using Context): Tree = - def quoteOwner(sym: Symbol): Symbol = - if sym.owner.isClass then sym else quoteOwner(sym.owner) - inContext(ctx.withOwner(quoteOwner(ctx.owner))) { + inContext(ctx.withOwner(ctx.owner.skipLocalOwners)) { PrepareInlineable.makeInlineable(tree) }