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

object may override a def causing ClassCastException in unrelated code #5429

Closed
scabug opened this issue Feb 1, 2012 · 9 comments
Closed
Assignees
Milestone

Comments

@scabug
Copy link

scabug commented Feb 1, 2012

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

@scabug
Copy link
Author

scabug commented Feb 1, 2012

Imported From: https://issues.scala-lang.org/browse/SI-5429?orig=1
Reporter: Rike-Benjamin Schuppner (debilski)
Affected Versions: 2.9.1, 2.10.0
See #5187

@scabug
Copy link
Author

scabug commented Feb 1, 2012

@paulp said:
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.

@scabug
Copy link
Author

scabug commented Feb 1, 2012

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

@scabug
Copy link
Author

scabug commented Feb 1, 2012

@paulp said:
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

@scabug
Copy link
Author

scabug commented Feb 2, 2012

@soc said:
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)

@scabug
Copy link
Author

scabug commented Feb 2, 2012

Rike-Benjamin Schuppner (debilski) said:
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.

@scabug
Copy link
Author

scabug commented Feb 2, 2012

@soc said:
Ouch. Didn't see the link, sorry.

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

@scabug
Copy link
Author

scabug commented Feb 2, 2012

@paulp said:
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.)

@scabug scabug closed this as completed Feb 29, 2012
@scabug
Copy link
Author

scabug commented Feb 29, 2012

@paulp said:
f55db64983

@scabug scabug added this to the 2.10.0 milestone Apr 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants