Skip to content

Commit

Permalink
Fix extending protected nested java classes (#21857)
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand authored Nov 6, 2024
2 parents 4e07efc + 14e46e8 commit 32aaa8a
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 14 deletions.
19 changes: 13 additions & 6 deletions compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,23 @@ 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, compUnitInfo = completer.compilationUnitInfo)
flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope, privateWithin: Symbol = NoSymbol,
)(using Context): Symbol = {
val cls = newClassSymbol(owner, name.toTypeName.unmangleClassName.decode, flags, completer, privateWithin, compUnitInfo = completer.compilationUnitInfo)
enterNew(owner, cls, completer, scope)
}

/** Enter module with given `name` into scope of `owner`.
*/
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,
compUnitInfo = completer.compilationUnitInfo)
enterNew(owner, module, completer, scope)
enterNew(owner, module.moduleClass, completer, scope)
Expand Down Expand Up @@ -103,13 +107,16 @@ object SymbolLoaders {
*/
def enterClassAndModule(
owner: Symbol, name: PreName, completer: SymbolLoader,
flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(using Context): Unit = {
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)
scope = scope,
privateWithin = privateWithin,
)
}

/** Enter all toplevel classes and objects in file `src` into package `owner`, provided
Expand Down
19 changes: 11 additions & 8 deletions compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -403,9 +403,10 @@ class ClassfileParser(

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)
Expand Down Expand Up @@ -1059,11 +1060,13 @@ class ClassfileParser(
private def enterOwnInnerClasses()(using Context, DataReader): Unit = {
def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile, jflags: Int) =
SymbolLoaders.enterClassAndModule(
getOwner(jflags),
entry.originalName,
new ClassfileLoader(file),
classTranslation.flags(jflags),
getScope(jflags))
getOwner(jflags),
entry.originalName,
new ClassfileLoader(file),
classTranslation.flags(jflags),
getScope(jflags),
getPrivateWithin(jflags),
)

for entry <- innerClasses.valuesIterator do
// create a new class member for immediate inner classes
Expand Down
7 changes: 7 additions & 0 deletions compiler/src/dotty/tools/dotc/printing/Formatting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,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
Expand Down
7 changes: 7 additions & 0 deletions tests/pos/i21631_joint/AbstractChannel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
public abstract class AbstractChannel {
protected AbstractChannel() {}
protected abstract AbstractUnsafe newUnsafe();
protected abstract class AbstractUnsafe {
public abstract void connect();
}
}
5 changes: 5 additions & 0 deletions tests/pos/i21631_joint/i21631.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Channel extends AbstractChannel() {
override def newUnsafe(): AbstractChannel#AbstractUnsafe = new AbstractUnsafe {
override def connect(): Unit = ???
}
}
7 changes: 7 additions & 0 deletions tests/pos/i21631_separ/AbstractChannel_1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
public abstract class AbstractChannel_1 {
protected AbstractChannel_1() {}
protected abstract AbstractUnsafe newUnsafe();
protected abstract class AbstractUnsafe {
public abstract void connect();
}
}
5 changes: 5 additions & 0 deletions tests/pos/i21631_separ/i21631_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Channel extends AbstractChannel_1() {
override def newUnsafe(): AbstractChannel_1#AbstractUnsafe = new AbstractUnsafe {
override def connect(): Unit = ???
}
}

0 comments on commit 32aaa8a

Please sign in to comment.