Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NoSuchMethodError when pattern matching on inner class (no outer accessor) #13096

Closed
SethTisue opened this issue Jul 17, 2021 · 3 comments · Fixed by #13124
Closed

NoSuchMethodError when pattern matching on inner class (no outer accessor) #13096

SethTisue opened this issue Jul 17, 2021 · 3 comments · Fixed by #13124
Assignees
Milestone

Comments

@SethTisue
Copy link
Member

SethTisue commented Jul 17, 2021

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. C2s 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...?

@dwijnand
Copy link
Member

So, what would the correct behavior — keep the check and make it work, or omit it?

Make it work, IMO. Looks like it's in one of posttyper's phases (oh, probably explicitOuter) that isn't capturing an outer reference in private class C2.

@SethTisue
Copy link
Member Author

SethTisue commented Jul 21, 2021

compilation of the test code fails under -Ycheck:all with

checking tests/run/i13096.scala after phase MegaPhase{elimOpaque, tryCatchPatterns, patternMatcher, explicitOuter, explicitSelf, elimByName, stringInterpolatorOpt}
exception while typing private[this] class C2() extends Object() {} of class class dotty.tools.dotc.ast.Trees$TypeDef # -1
exception while typing @scala.annotation.internal.SourceFile("tests/run/i13096.scala") class C1()
...
*** error while checking tests/run/i13096.scala after phase stringInterpolatorOpt ***
exception occurred while compiling tests/run/i13096.scala
java.lang.AssertionError: assertion failed:  class C2 tree does not define members: method C1$C2$$$outer, value $outer
expected: constructor C2, method C1$C2$$$outer, value $outer
defined:  while compiling tests/run/i13096.scala
Exception in thread "main" java.lang.AssertionError: assertion failed:  class C2 tree does not define members: method C1$C2$$$outer, value $outer
expected: constructor C2, method C1$C2$$$outer, value $outer
defined: 
	at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
	at dotty.tools.dotc.transform.TreeChecker$Checker.typedClassDef(TreeChecker.scala:482)
	at dotty.tools.dotc.typer.Typer.typedTypeOrClassDef$2(Typer.scala:2681)
	at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:2685)

SethTisue added a commit to SethTisue/dotty that referenced this issue Jul 21, 2021
fixes scala#13096

Co-authored-by: Dale Wijnand <dale.wijnand@gmail.com>
@SethTisue
Copy link
Member Author

PR: #13124

dwijnand added a commit to SethTisue/dotty that referenced this issue Jul 27, 2021
TryCatchPatterns is similar in spirit, so keep it with its buddy.

Fixes scala#13096

Co-authored-by: Dale Wijnand <dale.wijnand@gmail.com>
tanishiking pushed a commit to tanishiking/scala3 that referenced this issue Aug 10, 2021
TryCatchPatterns is similar in spirit, so keep it with its buddy.

Fixes scala#13096

Co-authored-by: Dale Wijnand <dale.wijnand@gmail.com>
@Kordyjan Kordyjan added this to the 3.1.0 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants