Description
tested on both 3.0.0 and 3.0.1-RC2
originally reported by Scala book author @cayhorstmann at scala/scala-xml#541
Minimized code
class C1 {
private class C2
new C2 match {
case c: C2 =>
}
}
object Test extends App {
new C1
}
Output
java.lang.NoSuchMethodError: C1$C2.C1$C2$$$outer()LC1;
at C1.<init>(S.scala:6)
which occurs because C2
simply doesn't have an outer accessor method. C2
s constructor accepts an outer reference, but doesn't do anything with it:
public C1$C2(C1);
descriptor: (LC1;)V
flags: ACC_PUBLIC
Code:
stack=1, locals=2, args_size=2
0: aload_0
1: invokespecial #14 // Method java/lang/Object."<init>":()V
4: return
Expectation
The runtime error occurs regardless of whether C2
is declared private[this]
or merely private
. It stops occurring if you declare C2
to be private[C1]
. (Perhaps the private
version fails because of the Scala 3 behavior where plain private
sometimes means private[this]
and sometimes means private[C1]
?)
Ironically, Scala 2 does the reverse: for private[this]
it gives C2
an outer accessor, but then the pattern match in C1
's constructor does not call it...!
So, what would the correct behavior — keep the check and make it work, or omit it? I don't know offhand, especially once you start considering the nuances of the different access levels the inner class might have. But I see there is a lot of previous lore in this area: #2156, scala/bug#4440, scala/bug#1419, maybe others...?