From 4a1a2eb8cbc6d5ff97d4c1d11ab2e0ed722ec872 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 25 Feb 2021 11:31:22 +0100 Subject: [PATCH] Use expanded names for inline proxies in traits Fixes #10477 --- .../tools/dotc/transform/AccessProxies.scala | 5 +++-- .../dotc/transform/ProtectedAccessors.scala | 3 ++- .../tools/dotc/typer/PrepareInlineable.scala | 6 +++-- tests/pos/i10477.scala | 9 ++++++++ tests/pos/i10477/A.scala | 22 +++++++++++++++++++ tests/pos/i10477/Test.scala | 15 +++++++++++++ 6 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 tests/pos/i10477.scala create mode 100644 tests/pos/i10477/A.scala create mode 100644 tests/pos/i10477/Test.scala diff --git a/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala b/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala index 6d6dc6fb3956..0399386a9e89 100644 --- a/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala +++ b/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala @@ -68,7 +68,8 @@ abstract class AccessProxies { trait Insert { import ast.tpd._ - def accessorNameKind: ClassifiedNameKind + /** The name of the accessor for definition with given `name` in given `site` */ + def accessorNameOf(name: TermName, site: Symbol)(using Context): TermName def needsAccessor(sym: Symbol)(using Context): Boolean def ifNoHost(reference: RefTree)(using Context): Tree = { @@ -134,7 +135,7 @@ abstract class AccessProxies { if (accessorClass.exists) { if accessorClass.is(Package) then accessorClass = ctx.owner.topLevelClass - val accessorName = accessorNameKind(accessed.name) + val accessorName = accessorNameOf(accessed.name, accessorClass) val accessorInfo = accessed.info.ensureMethodic.asSeenFrom(accessorClass.thisType, accessed.owner) val accessor = accessorSymbol(accessorClass, accessorName, accessorInfo, accessed) diff --git a/compiler/src/dotty/tools/dotc/transform/ProtectedAccessors.scala b/compiler/src/dotty/tools/dotc/transform/ProtectedAccessors.scala index b02f2723de91..8c59a192e09f 100644 --- a/compiler/src/dotty/tools/dotc/transform/ProtectedAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/ProtectedAccessors.scala @@ -6,6 +6,7 @@ import core.NameKinds._ import core.Symbols._ import core.Flags._ import core.Decorators._ +import core.Names.TermName import MegaPhase.MiniPhase import config.Printers.transforms @@ -51,7 +52,7 @@ class ProtectedAccessors extends MiniPhase { object Accessors extends AccessProxies { val insert: Insert = new Insert { - def accessorNameKind = ProtectedAccessorName + def accessorNameOf(name: TermName, site: Symbol)(using Context): TermName = ProtectedAccessorName(name) def needsAccessor(sym: Symbol)(using Context) = ProtectedAccessors.needsAccessor(sym) override def ifNoHost(reference: RefTree)(using Context): Tree = { diff --git a/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala index 56d89f982869..89966e072c5e 100644 --- a/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala +++ b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala @@ -13,7 +13,7 @@ import Decorators._ import NameKinds._ import StdNames.nme import Contexts._ -import Names.Name +import Names.{Name, TermName} import NameKinds.{InlineAccessorName, UniqueInlineName} import NameOps._ import Annotations._ @@ -40,7 +40,9 @@ object PrepareInlineable { /** A tree map which inserts accessors for non-public term members accessed from inlined code. */ abstract class MakeInlineableMap(val inlineSym: Symbol) extends TreeMap with Insert { - def accessorNameKind: PrefixNameKind = InlineAccessorName + def accessorNameOf(name: TermName, site: Symbol)(using Context): TermName = + val accName = InlineAccessorName(name) + if site.is(Trait) then accName.expandedName(site) else accName /** A definition needs an accessor if it is private, protected, or qualified private * and it is not part of the tree that gets inlined. The latter test is implemented diff --git a/tests/pos/i10477.scala b/tests/pos/i10477.scala new file mode 100644 index 000000000000..41d883c61b2b --- /dev/null +++ b/tests/pos/i10477.scala @@ -0,0 +1,9 @@ +trait A: + private def f: Int = 1 + inline def g = f +trait B: + private def f: Int = 1 + inline def h = f +class C extends A, B + + diff --git a/tests/pos/i10477/A.scala b/tests/pos/i10477/A.scala new file mode 100644 index 000000000000..27c6f59c68b2 --- /dev/null +++ b/tests/pos/i10477/A.scala @@ -0,0 +1,22 @@ +package gopher + +import scala.util.Try + +def await[F[_],T](f:F[T])(using am:CpsAsyncMonad[F]):T = ??? + +trait CpsAsyncMonad[F[_]]: + + def adoptCallbackStyle[A](source: (Try[A]=>Unit) => Unit): F[A] + +trait IChannel[F[_]:CpsAsyncMonad, A]: + + def aread:F[A] = + summon[CpsAsyncMonad[F]].adoptCallbackStyle(f => addReader(f)) + + inline def read: A = await(aread) + + def addReader(f: Try[A]=>Unit): Unit + + +trait IOChannel[F[_]:CpsAsyncMonad,I,O] extends IChannel[F,I] with OChannel[F,O] + diff --git a/tests/pos/i10477/Test.scala b/tests/pos/i10477/Test.scala new file mode 100644 index 000000000000..2e25bd4a8a6b --- /dev/null +++ b/tests/pos/i10477/Test.scala @@ -0,0 +1,15 @@ +package gopher + +import scala.util.Try + +trait OChannel[F[_]:CpsAsyncMonad, A]: + + def awrite(a:A):F[Unit] = + summon[CpsAsyncMonad[F]].adoptCallbackStyle(f => + addWriter(a, f) + ) + + inline def write(a:A): Unit = await(awrite(a)) + + def addWriter(a:A, f: Try[Unit]=>Unit): Unit +