From 90deb4ffa2fb6aed75bfee0a74ff7771032e8e92 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 26 Feb 2021 16:58:36 +0100 Subject: [PATCH 1/3] Collect package imports in TreeMapWithImplicits Fixes #11538 --- .../tools/dotc/ast/TreeMapWithImplicits.scala | 12 ++++++++-- tests/pos/i11538a.scala | 23 +++++++++++++++++++ tests/pos/i11538b.scala | 9 ++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 tests/pos/i11538a.scala create mode 100644 tests/pos/i11538b.scala diff --git a/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala b/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala index 98376c497868..9e61d8da6ac4 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala @@ -69,6 +69,12 @@ class TreeMapWithImplicits extends tpd.TreeMap { nestedCtx } + private def nestedPackageScopeCtx(tree: PackageDef)(using Context): Context = + tree.stats.foldLeft(ctx.withOwner(tree.symbol)) { + case (acc, stat: Import) => ctx.importContext(stat, stat.symbol) + case (acc, _) => acc + } + private def patternScopeCtx(pattern: Tree)(using Context): Context = { val nestedCtx = ctx.fresh.setNewScope new TreeTraverser { @@ -100,8 +106,10 @@ class TreeMapWithImplicits extends tpd.TreeMap { } case EmptyValDef => tree - case _: PackageDef | _: MemberDef => - super.transform(tree)(using localCtx) + case tree: PackageDef => + super.transform(tree)(using nestedPackageScopeCtx(tree)) + case _: MemberDef => + super.transform(tree)(using localCtx) case impl @ Template(constr, parents, self, _) => cpy.Template(tree)( transformSub(constr), diff --git a/tests/pos/i11538a.scala b/tests/pos/i11538a.scala new file mode 100644 index 000000000000..243900c43b44 --- /dev/null +++ b/tests/pos/i11538a.scala @@ -0,0 +1,23 @@ +package a: + + trait Printer[A]: + def print(a: A): Unit + + given Printer[String] with + def print(s: String) = println(s) + +package b: + + import a.{given, *} + + object test: + import scala.compiletime.{error, summonFrom} + + inline def summonStringPrinter = + summonFrom { + case given Printer[String] => () + case _ => error("Couldn't find a printer") + } + + val summoned = summon[Printer[String]] + val summonedFrom = summonStringPrinter diff --git a/tests/pos/i11538b.scala b/tests/pos/i11538b.scala new file mode 100644 index 000000000000..c061910b2e73 --- /dev/null +++ b/tests/pos/i11538b.scala @@ -0,0 +1,9 @@ +package a: + type Foo + given foo: Foo = ??? + +import a.{Foo, given} +object test: + inline def summonInlineFoo = scala.compiletime.summonInline[Foo] + val summoned = summon[Foo] + val summonedInline = summonInlineFoo From 6eddfe97f705ccaf65e344fb829d171669a4f550 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 1 Mar 2021 09:11:46 +0100 Subject: [PATCH 2/3] Collect imports in blocks Fixes #11557 --- .../dotty/tools/dotc/ast/TreeMapWithImplicits.scala | 11 +++++++---- .../tools/dotc/transform/TreeMapWithStages.scala | 6 +++--- tests/pos/i11557.scala | 12 ++++++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 tests/pos/i11557.scala diff --git a/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala b/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala index 9e61d8da6ac4..606c9f634b60 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala @@ -60,17 +60,20 @@ class TreeMapWithImplicits extends tpd.TreeMap { traverse(stats) } - private def nestedScopeCtx(defs: List[Tree])(using Context): Context = { + private def nestedScopeCtx(stats: List[Tree])(using Context): Context = { val nestedCtx = ctx.fresh.setNewScope - defs foreach { + stats.foreach { case d: DefTree if d.symbol.isOneOf(GivenOrImplicit) => nestedCtx.enter(d.symbol) case _ => } - nestedCtx + importScopeCtx(stats)(using nestedCtx) } private def nestedPackageScopeCtx(tree: PackageDef)(using Context): Context = - tree.stats.foldLeft(ctx.withOwner(tree.symbol)) { + importScopeCtx(tree.stats)(using ctx.withOwner(tree.symbol)) + + private def importScopeCtx(stats: List[Tree])(using Context): Context = + stats.foldLeft(ctx) { case (acc, stat: Import) => ctx.importContext(stat, stat.symbol) case (acc, _) => acc } diff --git a/compiler/src/dotty/tools/dotc/transform/TreeMapWithStages.scala b/compiler/src/dotty/tools/dotc/transform/TreeMapWithStages.scala index f678a1930758..c23e90352d10 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeMapWithStages.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeMapWithStages.scala @@ -46,7 +46,7 @@ abstract class TreeMapWithStages(@constructorOnly ictx: Context) extends TreeMap /** The quotation level of the definition of the locally defined symbol */ protected def levelOf(sym: Symbol): Int = levelOfMap.getOrElse(sym, 0) - /** Localy defined symbols seen so far by `StagingTransformer.transform` */ + /** Locally defined symbols seen so far by `StagingTransformer.transform` */ protected def localSymbols: List[Symbol] = enteredSyms /** If we are inside a quote or a splice */ @@ -74,7 +74,7 @@ abstract class TreeMapWithStages(@constructorOnly ictx: Context) extends TreeMap /** Transform the expression splice `splice` which contains the spliced `body`. */ protected def transformSplice(body: Tree, splice: Apply)(using Context): Tree - /** Transform the typee splice `splice` which contains the spliced `body`. */ + /** Transform the type splice `splice` which contains the spliced `body`. */ protected def transformSpliceType(body: Tree, splice: Select)(using Context): Tree override def transform(tree: Tree)(using Context): Tree = @@ -109,7 +109,7 @@ abstract class TreeMapWithStages(@constructorOnly ictx: Context) extends TreeMap try dropEmptyBlocks(quotedTree) match { case Spliced(t) => // '{ $x } --> x - // and adapt the refinment of `Quotes { type tasty: ... } ?=> Expr[T]` + // and adapt the refinement of `Quotes { type reflect: ... } ?=> Expr[T]` transform(t).asInstance(tree.tpe) case _ => transformQuotation(quotedTree, tree) } diff --git a/tests/pos/i11557.scala b/tests/pos/i11557.scala new file mode 100644 index 000000000000..f886a98d1727 --- /dev/null +++ b/tests/pos/i11557.scala @@ -0,0 +1,12 @@ +type MyEncoder + +class MyContext: + given intEncoder: MyEncoder = ??? + +def doEncoding(ctx: MyContext): Unit = + import ctx.{*, given} + summon[MyEncoder] + summonInlineMyEncoder() + +inline def summonInlineMyEncoder(): Unit = + compiletime.summonInline[MyEncoder] From d43764987022a65db7b75f514064c9b8f90db9bb Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 24 Feb 2021 11:47:17 +0100 Subject: [PATCH 3/3] Add top-level definitions to scope in TreeMapWithImplicits Fixes #11479 --- .../tools/dotc/ast/TreeMapWithImplicits.scala | 14 ++++++++++++-- tests/pos-macros/i11479/Macro_1.scala | 3 +++ tests/pos-macros/i11479/Test_2.scala | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 tests/pos-macros/i11479/Macro_1.scala create mode 100644 tests/pos-macros/i11479/Test_2.scala diff --git a/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala b/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala index 606c9f634b60..a3abb1f5aaf9 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala @@ -5,6 +5,7 @@ import Trees._ import core.Contexts._ import core.ContextOps.enter import core.Flags._ +import core.NameOps._ import core.Symbols._ import core.TypeError @@ -69,8 +70,17 @@ class TreeMapWithImplicits extends tpd.TreeMap { importScopeCtx(stats)(using nestedCtx) } - private def nestedPackageScopeCtx(tree: PackageDef)(using Context): Context = - importScopeCtx(tree.stats)(using ctx.withOwner(tree.symbol)) + private def nestedPackageScopeCtx(tree: PackageDef)(using Context): Context = { + val nestedCtx = ctx.withOwner(tree.symbol).fresh.setNewScope + for + packageDecl <- tree.symbol.moduleClass.asClass.info.decls.toList + if packageDecl.isTerm && packageDecl.name.isPackageObjectName + decl <- packageDecl.info.decls.toList + if decl.isTerm && decl.isOneOf(GivenOrImplicit) + do + nestedCtx.enter(decl) + importScopeCtx(tree.stats)(using nestedCtx) + } private def importScopeCtx(stats: List[Tree])(using Context): Context = stats.foldLeft(ctx) { diff --git a/tests/pos-macros/i11479/Macro_1.scala b/tests/pos-macros/i11479/Macro_1.scala new file mode 100644 index 000000000000..86fce90bbf06 --- /dev/null +++ b/tests/pos-macros/i11479/Macro_1.scala @@ -0,0 +1,3 @@ +trait Foo +given Foo: Foo with {} +inline def summonFoo(): Foo = scala.compiletime.summonInline[Foo] diff --git a/tests/pos-macros/i11479/Test_2.scala b/tests/pos-macros/i11479/Test_2.scala new file mode 100644 index 000000000000..9f1fc238aa74 --- /dev/null +++ b/tests/pos-macros/i11479/Test_2.scala @@ -0,0 +1 @@ +def test: Unit = summonFoo()