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

object may override a def causing ClassCastException in unrelated code

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: Scala 2.9.1, Scala 2.10.0
    • Fix Version/s: Scala 2.10.0
    • Labels:
      None
    • Environment:

      Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29). Mac OS X 10.7.
      Scala version 2.10.0.rdev-4244-2012-01-24-geb561e3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29). Mac OS X 10.7.

      Description

      Given some class with a method

      class A {
        def m() = 5
      }
      

      it is currently possible to override this method with an object definition:

      class B extends A {
        object m
      }
      

      The compiler won't complain about this (and I'm not sure what the specification says about this specific situation), however the code will break wherever A is expected:

      scala> ((new B): B).m    // compiles and runs
      res: object B#m = B$m$@1e450448
      scala> ((new B): A).m
      java.lang.ClassCastException
      

      As a possibly related phenomenon: It is currently not possible to override a parentheses-less def with an object.

      class A2 {
        def m2 = 5
      }
      class B2 extends A2 {
        object m2
      }
      error: overriding method m in class A2 of type => Int;
       object m2 cannot be used here - classes and objects can only override abstract types
             class B2 extends A2 { object m2 }
                                        ^
      

      Related: https://groups.google.com/forum/#!topic/scala-user/TOuQ2-Jr_R8
      Related: http://stackoverflow.com/questions/7584400/overriding-a-method-with-an-object

        Issue Links

          Activity

          Hide
          Paul Phillips added a comment -

          The error message is misleading, but you can override m2 with an object fine. You just can't override a method returning "Int" with a method returning "m2.type". And you have to override it.

          class A2 {
            def m2: Any = 5
          }
          class B2 extends A2 {
            override object m2
          }
          

          I've fixed the overriding bug, will check in shortly.

          Show
          Paul Phillips added a comment - The error message is misleading, but you can override m2 with an object fine. You just can't override a method returning "Int" with a method returning "m2.type". And you have to override it. class A2 { def m2: Any = 5 } class B2 extends A2 { override object m2 } I've fixed the overriding bug, will check in shortly.
          Hide
          Paul Phillips added a comment -

          Sorry, I see that doesn't work in 2.9.1. It does in trunk though. I wonder when that changed...

          Show
          Paul Phillips added a comment - Sorry, I see that doesn't work in 2.9.1. It does in trunk though. I wonder when that changed...
          Hide
          Paul Phillips added a comment -

          Looks like I unwittingly made that possible in r25634 when implementing the experimental ability for other members to override objects. (This being distinct from what I accidentally enabled, objects overriding other members.)

          % scala -Yoverride-objects
          Welcome to Scala version 2.10.0.rdev-4299-2012-01-30-g366fae9 (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)
          
          class A2 { object m2 }
          class B2 extends A2 { override object m2 }
          
          // Exiting paste mode, now interpreting.
          
          defined class A2
          defined class B2
          
          Show
          Paul Phillips added a comment - Looks like I unwittingly made that possible in r25634 when implementing the experimental ability for other members to override objects. (This being distinct from what I accidentally enabled, objects overriding other members.) % scala -Yoverride-objects Welcome to Scala version 2.10.0.rdev-4299-2012-01-30-g366fae9 (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) class A2 { object m2 } class B2 extends A2 { override object m2 } // Exiting paste mode, now interpreting. defined class A2 defined class B2
          Hide
          Simon Ochsenreither added a comment -

          This is probably slightly related and causes an `java.lang.VerifyError` on Scala version 2.10.0.rdev-4302-2012-02-01-g37bcff7:

          class A {
             object m { override def toString = "object m" }
          }
          
          class B extends A {
             def m() = "def m"
          }
          
          (new B).m()
          
          java.lang.VerifyError: class B overrides final method m.()LA$m$;
          	at java.lang.ClassLoader.defineClass1(Native Method)
          	at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
          	at java.lang.ClassLoader.defineClass(ClassLoader.java:634)
          	at scala.tools.nsc.interpreter.AbstractFileClassLoader.findClass(AbstractFileClassLoader.scala:67)
          	at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
          	at scala.tools.nsc.interpreter.AbstractFileClassLoader.scala$tools$nsc$util$ScalaClassLoader$$super$loadClass(AbstractFileClassLoader.scala:18)
          	at scala.tools.nsc.util.ScalaClassLoader$class.loadClass(ScalaClassLoader.scala:63)
          	at scala.tools.nsc.interpreter.AbstractFileClassLoader.loadClass(AbstractFileClassLoader.scala:56)
          	at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
          	at .<init>(<console>:10)
          	at .<clinit>(<console>)
          	at .<init>(<console>:11)
          	at .<clinit>(<console>)
          	at $print(<console>)
          	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
          	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
          	at java.lang.reflect.Method.invoke(Method.java:601)
          	at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:761)
          	at scala.tools.nsc.interpreter.IMain$Request$$anonfun$13.apply(IMain.scala:1002)
          	at scala.tools.nsc.interpreter.Line.scala$tools$nsc$interpreter$Line$$runAndSetState(Line.scala:41)
          	at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:47)
          	at scala.tools.nsc.io.package$$anon$2.run(package.scala:19)
          	at java.lang.Thread.run(Thread.java:722)
          
          Show
          Simon Ochsenreither added a comment - This is probably slightly related and causes an `java.lang.VerifyError` on Scala version 2.10.0.rdev-4302-2012-02-01-g37bcff7: class A { object m { override def toString = "object m" } } class B extends A { def m() = "def m" } (new B).m() java.lang.VerifyError: class B overrides final method m.()LA$m$; at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:791) at java.lang.ClassLoader.defineClass(ClassLoader.java:634) at scala.tools.nsc.interpreter.AbstractFileClassLoader.findClass(AbstractFileClassLoader.scala:67) at java.lang.ClassLoader.loadClass(ClassLoader.java:423) at scala.tools.nsc.interpreter.AbstractFileClassLoader.scala$tools$nsc$util$ScalaClassLoader$$super$loadClass(AbstractFileClassLoader.scala:18) at scala.tools.nsc.util.ScalaClassLoader$class.loadClass(ScalaClassLoader.scala:63) at scala.tools.nsc.interpreter.AbstractFileClassLoader.loadClass(AbstractFileClassLoader.scala:56) at java.lang.ClassLoader.loadClass(ClassLoader.java:356) at .<init>(<console>:10) at .<clinit>(<console>) at .<init>(<console>:11) at .<clinit>(<console>) at $print(<console>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:761) at scala.tools.nsc.interpreter.IMain$Request$$anonfun$13.apply(IMain.scala:1002) at scala.tools.nsc.interpreter.Line.scala$tools$nsc$interpreter$Line$$runAndSetState(Line.scala:41) at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:47) at scala.tools.nsc.io.package$$anon$2.run(package.scala:19) at java.lang.Thread.run(Thread.java:722)
          Hide
          Rike-Benjamin Schuppner added a comment -

          Yes, that’s the one which was also stated in the Stackoverflow link. As far as I see it, it’s been fixed in paulp’s objects-and-overrides branch as well.

          Show
          Rike-Benjamin Schuppner added a comment - Yes, that’s the one which was also stated in the Stackoverflow link. As far as I see it, it’s been fixed in paulp’s objects-and-overrides branch as well.
          Hide
          Simon Ochsenreither added a comment -

          Ouch. Didn't see the link, sorry.

          I also checked it with `scala -Yoverride-objects` but the problem was the same ...

          Show
          Simon Ochsenreither added a comment - Ouch. Didn't see the link, sorry. I also checked it with `scala -Yoverride-objects` but the problem was the same ...
          Hide
          Paul Phillips added a comment -

          My guess is what you didn't try is the objects-and-overrides branch on github, which is where it is fixed. (The -Yoverride-objects option is irrelevant.)

          Show
          Paul Phillips added a comment - My guess is what you didn't try is the objects-and-overrides branch on github, which is where it is fixed. (The -Yoverride-objects option is irrelevant.)
          Hide
          Paul Phillips added a comment -

          f55db64983

          Show
          Paul Phillips added a comment - f55db64983

            People

            • Assignee:
              Paul Phillips
              Reporter:
              Rike-Benjamin Schuppner
            • Votes:
              2 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development