From f9a0010a07d7e9366fe657827576ce3913558af6 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 29 Oct 2024 17:52:13 +0000 Subject: [PATCH 1/3] Fix extending protected nested java classes PR 21362 added an accessibility fix to Erasure, but that revealed a mistake in determining the accessibility of inner java classes, which I'm now fixing. [Cherry-picked 17dadf791a5b42eb406227901b1c16940e1537cb] --- .../dotty/tools/dotc/core/classfile/ClassfileParser.scala | 3 ++- compiler/src/dotty/tools/dotc/printing/Formatting.scala | 7 +++++++ tests/pos/i21631_joint/AbstractChannel.java | 7 +++++++ tests/pos/i21631_joint/i21631.scala | 5 +++++ tests/pos/i21631_separ/AbstractChannel_1.java | 7 +++++++ tests/pos/i21631_separ/i21631_2.scala | 5 +++++ 6 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i21631_joint/AbstractChannel.java create mode 100644 tests/pos/i21631_joint/i21631.scala create mode 100644 tests/pos/i21631_separ/AbstractChannel_1.java create mode 100644 tests/pos/i21631_separ/i21631_2.scala diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index dd930834e837..c5c844907029 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -226,7 +226,8 @@ class ClassfileParser( classRoot.setFlag(sflags) moduleRoot.setFlag(Flags.JavaDefined | Flags.ModuleClassCreationFlags) - val privateWithin = getPrivateWithin(jflags) + val jflags1 = innerClasses.get(currentClassName.toString).fold(jflags: Int)(_.jflags) + val privateWithin = getPrivateWithin(jflags1) classRoot.setPrivateWithin(privateWithin) moduleRoot.setPrivateWithin(privateWithin) diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index 3ae903f04a23..11f9057e3da7 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -112,6 +112,13 @@ object Formatting { case Atoms.Range(lo, hi) => CtxShow(s"Range(${toStr(lo.toList)}, ${toStr(hi.toList)})") end given + given Show[ast.untpd.Modifiers] with + def show(x: ast.untpd.Modifiers) = + CtxShow(s"Modifiers(${toStr(x.flags)}, ${toStr(x.privateWithin)}, ${toStr(x.annotations)}, ${toStr(x.mods)})") + + given Show[ast.untpd.Mod] with + def show(x: ast.untpd.Mod) = CtxShow(s"Mod(${toStr(x.flags)})") + given Show[Showable] = ShowAny given Show[Shown] = ShowAny given Show[Int] = ShowAny diff --git a/tests/pos/i21631_joint/AbstractChannel.java b/tests/pos/i21631_joint/AbstractChannel.java new file mode 100644 index 000000000000..fbcd04549def --- /dev/null +++ b/tests/pos/i21631_joint/AbstractChannel.java @@ -0,0 +1,7 @@ +public abstract class AbstractChannel { + protected AbstractChannel() {} + protected abstract AbstractUnsafe newUnsafe(); + protected abstract class AbstractUnsafe { + public abstract void connect(); + } +} diff --git a/tests/pos/i21631_joint/i21631.scala b/tests/pos/i21631_joint/i21631.scala new file mode 100644 index 000000000000..c567d75b1375 --- /dev/null +++ b/tests/pos/i21631_joint/i21631.scala @@ -0,0 +1,5 @@ +class Channel extends AbstractChannel() { + override def newUnsafe(): AbstractChannel#AbstractUnsafe = new AbstractUnsafe { + override def connect(): Unit = ??? + } +} diff --git a/tests/pos/i21631_separ/AbstractChannel_1.java b/tests/pos/i21631_separ/AbstractChannel_1.java new file mode 100644 index 000000000000..e89767d6d73e --- /dev/null +++ b/tests/pos/i21631_separ/AbstractChannel_1.java @@ -0,0 +1,7 @@ +public abstract class AbstractChannel_1 { + protected AbstractChannel_1() {} + protected abstract AbstractUnsafe newUnsafe(); + protected abstract class AbstractUnsafe { + public abstract void connect(); + } +} diff --git a/tests/pos/i21631_separ/i21631_2.scala b/tests/pos/i21631_separ/i21631_2.scala new file mode 100644 index 000000000000..89524e333920 --- /dev/null +++ b/tests/pos/i21631_separ/i21631_2.scala @@ -0,0 +1,5 @@ +class Channel extends AbstractChannel_1() { + override def newUnsafe(): AbstractChannel_1#AbstractUnsafe = new AbstractUnsafe { + override def connect(): Unit = ??? + } +} From 54c9ce74202630f89da575d5dff5fc7a8672a1d6 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 31 Oct 2024 18:44:04 +0000 Subject: [PATCH 2/3] Set privateWithin when creating java inner classes [Cherry-picked 350215dcaad554accccef37502033439a6d09caf] --- .../dotty/tools/dotc/core/SymbolLoaders.scala | 3 ++- .../dotc/core/classfile/ClassfileParser.scala | 19 ++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 68505f45a3e2..e079182d99b6 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -100,13 +100,14 @@ object SymbolLoaders { */ def enterClassAndModule( owner: Symbol, name: PreName, completer: SymbolLoader, - flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(using Context): Unit = { + flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(using Context): (Symbol, Symbol) = { val clazz = enterClass(owner, name, completer, flags, scope) val module = enterModule( owner, name, completer, modFlags = flags.toTermFlags & RetainedModuleValFlags, clsFlags = flags.toTypeFlags & RetainedModuleClassFlags, scope = scope) + (clazz, module) } /** Enter all toplevel classes and objects in file `src` into package `owner`, provided diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index c5c844907029..8e2838b0c955 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -226,12 +226,12 @@ class ClassfileParser( classRoot.setFlag(sflags) moduleRoot.setFlag(Flags.JavaDefined | Flags.ModuleClassCreationFlags) - val jflags1 = innerClasses.get(currentClassName.toString).fold(jflags: Int)(_.jflags) - val privateWithin = getPrivateWithin(jflags1) + val privateWithin = getPrivateWithin(jflags) - classRoot.setPrivateWithin(privateWithin) - moduleRoot.setPrivateWithin(privateWithin) - moduleRoot.sourceModule.setPrivateWithin(privateWithin) + if privateWithin.exists then + classRoot.setPrivateWithin(privateWithin) + moduleRoot.setPrivateWithin(privateWithin) + moduleRoot.sourceModule.setPrivateWithin(privateWithin) for (i <- 0 until in.nextChar) parseMember(method = false) for (i <- 0 until in.nextChar) parseMember(method = true) @@ -884,13 +884,18 @@ class ClassfileParser( */ private def enterOwnInnerClasses()(using Context, DataReader): Unit = { def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile, jflags: Int) = - SymbolLoaders.enterClassAndModule( + val (cls, mod) = SymbolLoaders.enterClassAndModule( getOwner(jflags), - entry.originalName, + entry.originalName, new ClassfileLoader(file), classTranslation.flags(jflags), getScope(jflags)) + val privateWithin = getPrivateWithin(jflags) + cls.setPrivateWithin(privateWithin) + mod.setPrivateWithin(privateWithin) + mod.sourceModule.setPrivateWithin(privateWithin) + for entry <- innerClasses.valuesIterator do // create a new class member for immediate inner classes if entry.outer.name == currentClassName then From 023d0a2fcbe66fe74b2c7248654cccfa161aadd5 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Wed, 4 Dec 2024 14:26:08 +0100 Subject: [PATCH 3/3] Push java inner class privateWithin setting [Cherry-picked 14e46e845d0775538253560c599c1b43c3bfb880][modified] --- .../dotty/tools/dotc/core/SymbolLoaders.scala | 20 ++++++++++++------- .../dotc/core/classfile/ClassfileParser.scala | 17 +++++++--------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index e079182d99b6..10ff88d34ee7 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -48,8 +48,9 @@ object SymbolLoaders { */ def enterClass( owner: Symbol, name: PreName, completer: SymbolLoader, - flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(using Context): Symbol = { - val cls = newClassSymbol(owner, name.toTypeName.unmangleClassName.decode, flags, completer, assocFile = completer.sourceFileOrNull) + flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope, privateWithin: Symbol = NoSymbol, + )(using Context): Symbol = { + val cls = newClassSymbol(owner, name.toTypeName.unmangleClassName.decode, flags, completer, privateWithin, assocFile = completer.sourceFileOrNull) enterNew(owner, cls, completer, scope) } @@ -57,10 +58,13 @@ object SymbolLoaders { */ def enterModule( owner: Symbol, name: PreName, completer: SymbolLoader, - modFlags: FlagSet = EmptyFlags, clsFlags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(using Context): Symbol = { + modFlags: FlagSet = EmptyFlags, clsFlags: FlagSet = EmptyFlags, + scope: Scope = EmptyScope, privateWithin: Symbol = NoSymbol, + )(using Context): Symbol = { val module = newModuleSymbol( owner, name.toTermName.decode, modFlags, clsFlags, (module, _) => completer.proxy.withDecls(newScope).withSourceModule(module), + privateWithin, assocFile = completer.sourceFileOrNull) enterNew(owner, module, completer, scope) enterNew(owner, module.moduleClass, completer, scope) @@ -100,14 +104,16 @@ object SymbolLoaders { */ def enterClassAndModule( owner: Symbol, name: PreName, completer: SymbolLoader, - flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(using Context): (Symbol, Symbol) = { - val clazz = enterClass(owner, name, completer, flags, scope) + flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope, privateWithin: Symbol = NoSymbol, + )(using Context): Unit = { + val clazz = enterClass(owner, name, completer, flags, scope, privateWithin) val module = enterModule( owner, name, completer, modFlags = flags.toTermFlags & RetainedModuleValFlags, clsFlags = flags.toTypeFlags & RetainedModuleClassFlags, - scope = scope) - (clazz, module) + scope = scope, + privateWithin = privateWithin, + ) } /** Enter all toplevel classes and objects in file `src` into package `owner`, provided diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index 8e2838b0c955..c20b6c73b1ea 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -884,17 +884,14 @@ class ClassfileParser( */ private def enterOwnInnerClasses()(using Context, DataReader): Unit = { def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile, jflags: Int) = - val (cls, mod) = SymbolLoaders.enterClassAndModule( - getOwner(jflags), + SymbolLoaders.enterClassAndModule( + getOwner(jflags), entry.originalName, - new ClassfileLoader(file), - classTranslation.flags(jflags), - getScope(jflags)) - - val privateWithin = getPrivateWithin(jflags) - cls.setPrivateWithin(privateWithin) - mod.setPrivateWithin(privateWithin) - mod.sourceModule.setPrivateWithin(privateWithin) + new ClassfileLoader(file), + classTranslation.flags(jflags), + getScope(jflags), + getPrivateWithin(jflags), + ) for entry <- innerClasses.valuesIterator do // create a new class member for immediate inner classes