diff --git a/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala b/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala index 98376c497868..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 @@ -60,15 +61,33 @@ 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 = { + 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) { + 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 +119,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/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-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() 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 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]