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

Case Class Factory Constructor Inlining Fails to Invoke Companion Constructor

    Details

      Description

      See the following paste. It appears that the inlining of case class constructors/deconstructors fails to invoke the constructor for the companion object, which is counter to the specification.

      Welcome to Scala version 2.10.0.rdev-4009-2011-12-13-g6912ff8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29).
      Type in expressions to have them evaluated.
      Type :help for more information.

      scala> :paste
      // Entering paste mode (ctrl-D to finish)
      
      case class Test(a: Int)
      object Test {
        println("here")
      }
      
      // Exiting paste mode, now interpreting.
      
      defined class Test
      defined module Test
      
      scala> val Test(a) = Test(42)
      a: Int = 42
      
      scala> Test
      here
      res0: Test.type = Test$@78da5318
      

        Issue Links

          Activity

          Hide
          Jason Zaugg added a comment -

          My proposed fix for SI-4859 stopped just short of fixing this problem, but it shows all the places that need to be touched when we decide to do so.

          Show
          Jason Zaugg added a comment - My proposed fix for SI-4859 stopped just short of fixing this problem, but it shows all the places that need to be touched when we decide to do so.
          Hide
          Jason Zaugg added a comment -

          I discussed this with Martin recently, his thoughts:

          • Accessing a nested Java static classes doesn't run the static initializer of the enclosing class
          • People might be surprised by a performance difference between nested and top level modules
          • But, the arguments for forcing initialization do make sense.
          • We might investigate a scheme in which the constructor of a nested module initializes it's enclosing module. This would give us the desired semantics without the penalty of the outer module load at every access of the nested module.
          Show
          Jason Zaugg added a comment - I discussed this with Martin recently, his thoughts: Accessing a nested Java static classes doesn't run the static initializer of the enclosing class People might be surprised by a performance difference between nested and top level modules But, the arguments for forcing initialization do make sense. We might investigate a scheme in which the constructor of a nested module initializes it's enclosing module. This would give us the desired semantics without the penalty of the outer module load at every access of the nested module.
          Hide
          Jason Zaugg added a comment -

          Rescheduling for 2.11, I don't want to change the semantics for a minor release.

          Show
          Jason Zaugg added a comment - Rescheduling for 2.11, I don't want to change the semantics for a minor release.
          Hide
          Adriaan Moors added a comment -

          Unassigning and rescheduling to M6 as previous deadline was missed.

          Show
          Adriaan Moors added a comment - Unassigning and rescheduling to M6 as previous deadline was missed.
          Hide
          Jason Zaugg added a comment -

          Another example. This stems from use of isExprSafeToInline in Erasure#unbox1.

          topic/typer-crash-cleanup /code/scala tail sandbox/{t1,c}.scala
          ==> sandbox/t1.scala <==
          object T { println("!!!"); val x: Unit = () }
          ==> sandbox/c.scala <==
          object C {
            def main(args: Array[String]) {
              Some[Unit](T.x)
            }
          }
          topic/typer-crash-cleanup /code/scala qbin/scalac -d sandbox -Xprint:erasure sandbox/{t1,c}.scala
          [[syntax trees at end of                   erasure]] // t1.scala
          package <empty> {
            object T extends Object {
              def <init>(): T.type = {
                T.super.<init>();
                ()
              };
              private[this] val x: scala.runtime.BoxedUnit = scala.runtime.BoxedUnit.UNIT;
              <stable> <accessor> def x(): Unit = ()
            }
          }
          
           // c.scala
          package <empty> {
            object C extends Object {
              def <init>(): C.type = {
                C.super.<init>();
                ()
              };
              def main(args: Array[String]): Unit = {
                new Some(scala.runtime.BoxedUnit.UNIT);
                ()
              }
            }
          }
          
          Show
          Jason Zaugg added a comment - Another example. This stems from use of isExprSafeToInline in Erasure#unbox1 . topic/typer-crash-cleanup /code/scala tail sandbox/{t1,c}.scala ==> sandbox/t1.scala <== object T { println("!!!"); val x: Unit = () } ==> sandbox/c.scala <== object C { def main(args: Array[String]) { Some[Unit](T.x) } } topic/typer-crash-cleanup /code/scala qbin/scalac -d sandbox -Xprint:erasure sandbox/{t1,c}.scala [[syntax trees at end of erasure]] // t1.scala package <empty> { object T extends Object { def <init>(): T.type = { T.super.<init>(); () }; private[this] val x: scala.runtime.BoxedUnit = scala.runtime.BoxedUnit.UNIT; <stable> <accessor> def x(): Unit = () } } // c.scala package <empty> { object C extends Object { def <init>(): C.type = { C.super.<init>(); () }; def main(args: Array[String]): Unit = { new Some(scala.runtime.BoxedUnit.UNIT); () } } }

            People

            • Assignee:
              Unassigned
              Reporter:
              Daniel Spiewak
            • Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

              • Created:
                Updated:

                Development