Scala Programming Language
  1. Scala Programming Language
  2. SI-4440

correct outer check for match on final inner class

    Details

      Description

      === What steps will reproduce the problem (please be specific and use wikiformatting)? ===

      The following code crashes with a `NoSuchMethodError`:

      final class Outer {
      
        sealed trait Inner
      
        final case class Inner1(foo: Int) extends Inner
      
        val inner: Outer#Inner = Inner1(0)
      
        def bar = inner match {
          case Inner1(i) => i
        }
      }
      
      object Crash {
        def main(args: Array[String]) {
          println((new Outer).bar)
        }
      }
      

      The crash does not happen when one of these changes is applied:

      • `Inner` is a `sealed abstract class` instead of a `sealed trait`
      • the type of `val inner` is not a type projection but just `Inner`
      • the class `Inner1` is not marked final

      The `NoSuchMethodError` at runtime:

      java.lang.NoSuchMethodError: Outer$$Inner1.Outer$$Inner1$$$$$$outer()LOuter;
      	at Outer.bar(finalcase.scala:9)
      	at Crash$$.main(finalcase.scala:16)
      	at Crash.main(finalcase.scala)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      	at java.lang.reflect.Method.invoke(Method.java:597)
      	at scala.tools.nsc.util.ScalaClassLoader$$$$anonfun$$run$$1.apply(ScalaClassLoader.scala:81)
      	at scala.tools.nsc.util.ScalaClassLoader$$class.asContext(ScalaClassLoader.scala:24)
      	at scala.tools.nsc.util.ScalaClassLoader$$URLClassLoader.asContext(ScalaClassLoader.scala:91)
      	at scala.tools.nsc.util.ScalaClassLoader$$class.run(ScalaClassLoader.scala:81)
      	at scala.tools.nsc.util.ScalaClassLoader$$URLClassLoader.run(ScalaClassLoader.scala:104)
      	at scala.tools.nsc.ObjectRunner$$.run(ObjectRunner.scala:33)
      	at scala.tools.nsc.ObjectRunner$$.runAndCatch(ObjectRunner.scala:40)
      	at scala.tools.nsc.MainGenericRunner$$.runTarget$$1(MainGenericRunner.scala:61)
      	at scala.tools.nsc.MainGenericRunner$$.process(MainGenericRunner.scala:85)
      	at scala.tools.nsc.MainGenericRunner$$.main(MainGenericRunner.scala:33)
      	at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
      

      === What versions of the following are you using? ===

      • Scala: 2.9.0.RC1
      • Java: 1.6.0_24
      • Operating system: OS X 10.6.7

        Activity

        Hide
        Adriaan Moors added a comment -

        In 2.11 we'll do the right thing: the final modifier is not a sufficient condition for omitting the outer pointer. If we can come up with some kind of optimization (hard to do if you can't assume a closed world), we'll optimize memory usage there.

        In the mean time, if you don't want an outer pointer, don't nest your class.

        Show
        Adriaan Moors added a comment - In 2.11 we'll do the right thing: the final modifier is not a sufficient condition for omitting the outer pointer. If we can come up with some kind of optimization (hard to do if you can't assume a closed world), we'll optimize memory usage there. In the mean time, if you don't want an outer pointer, don't nest your class.
        Hide
        Jason Zaugg added a comment - - edited

        Perhaps a class annotation @noouter?

        Show
        Jason Zaugg added a comment - - edited Perhaps a class annotation @noouter ?
        Hide
        Paolo G. Giarrusso added a comment -

        I and Miguel Garcia discussed this bug again on a pull request. Since the current situation was not obvious, here's a link to the post where I explain the current problem:

        https://github.com/scala/scala/pull/2634#issuecomment-19173210
        Code and results are at https://gist.github.com/Blaisorblade/5745026.

        I might post here an updated summary in my copious free time, but until then, I hope that link helps.

        Show
        Paolo G. Giarrusso added a comment - I and Miguel Garcia discussed this bug again on a pull request. Since the current situation was not obvious, here's a link to the post where I explain the current problem: https://github.com/scala/scala/pull/2634#issuecomment-19173210 Code and results are at https://gist.github.com/Blaisorblade/5745026 . I might post here an updated summary in my copious free time, but until then, I hope that link helps.
        Hide
        Paolo G. Giarrusso added a comment -

        The optimization should still be valid when any of the following conditions holds:

        • the Inner class is only visible within the compilation unit, say because Inner (or Outer) is private (but not private[x]), and the compilation unit doesn't use @outer
        • the inner class is anonymous (so it can't be used in a pattern match - right?)
        • the inner class is annotated with @noouter (Jason Zaugg's proposal).

        Here's also a link to the email conversation, for completeness (not sure it contains anything more):
        https://groups.google.com/d/msg/scala-internals/jQiRINTvhZQ/GrxAJjccdmUJ

        Show
        Paolo G. Giarrusso added a comment - The optimization should still be valid when any of the following conditions holds: the Inner class is only visible within the compilation unit, say because Inner (or Outer) is private (but not private [x] ), and the compilation unit doesn't use @outer the inner class is anonymous (so it can't be used in a pattern match - right?) the inner class is annotated with @noouter (Jason Zaugg's proposal). Here's also a link to the email conversation, for completeness (not sure it contains anything more): https://groups.google.com/d/msg/scala-internals/jQiRINTvhZQ/GrxAJjccdmUJ
        Hide
        Grzegorz Kossakowski added a comment -

        Unassigning and rescheduling to M7 as previous deadline was missed.

        Show
        Grzegorz Kossakowski added a comment - Unassigning and rescheduling to M7 as previous deadline was missed.

          People

          • Assignee:
            Unassigned
            Reporter:
            Moritz Uhlig
          • Votes:
            0 Vote for this issue
            Watchers:
            12 Start watching this issue

            Dates

            • Created:
              Updated:

              Development