Description
A.scala
:
class A(val member: Int)
class SubA(member: Int) extends A(member)
B.scala
:
class B(member: Int) extends SubA(member)
If you try to compile these two files together everything works fine, but if you first compile A.scala
and then B.scala
you get:
Exception in thread "main" java.lang.AssertionError: assertion failed: private method member in class SubA in try/exp/A.scala accessed from method member in class B in try/exp/B.scala
at scala.Predef$.assert(Predef.scala:165)
at dotty.tools.dotc.transform.ExpandPrivate.ensurePrivateAccessible(ExpandPrivate.scala:84)
The issue is that ExpandPrivate
only transforms PrivateParamAccesor
in trees:
override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo) = {
val sym = tree.symbol
tree.rhs match {
case Apply(sel @ Select(_: Super, _), _)
if sym.is(PrivateParamAccessor) && sel.symbol.is(ParamAccessor) && sym.name == sel.symbol.name =>
sym.ensureNotPrivate.installAfter(thisTransform)
case _ =>
if (isVCPrivateParamAccessor(sym))
sym.ensureNotPrivate.installAfter(thisTransform)
}
tree
}
So when we compile A.scala
and B.scala
together, the denotation for SubA#member
gets transformed as expected, but when we do separate compilation, we see SubA#member
as private, so ExpandPrivate
explodes.
Note: see the comment at the top of ExpandPrivate
if you're wondering why private param forwarders need to be made non-private.
I'm unsure how to fix this since it seems that we need access to the tree to decide whether or not the param forwarder should be made non-private. Maybe we need an extra flag to signal that a param forwarder forwards to an inherited param accessor with the same name?
This issue is blocking the Super Bootstrap