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

scala.util.Try.apply produces java.lang.ClassCastException #6306

Closed
scabug opened this issue Sep 2, 2012 · 12 comments
Closed

scala.util.Try.apply produces java.lang.ClassCastException #6306

scabug opened this issue Sep 2, 2012 · 12 comments
Assignees
Milestone

Comments

@scabug
Copy link

@scabug scabug commented Sep 2, 2012

A weird runtime exception by Try.apply

$ scala-2.10.0-M7/bin/scala -e 'scala.util.Try(1.toString)'
java.lang.ClassCastException: java.lang.String cannot be cast to scala.Function0
at Main$$anon$1.(scalacmd5144416276510110047.scala:1)
at Main$.main(scalacmd5144416276510110047.scala:1)
at Main.main(scalacmd5144416276510110047.scala)
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:616)
at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:71)
....

Same error can be reproduced in repl and in real compiled application using Test.scala:

object Test {
def main(args: Array[String]) {
scala.util.Try(1.toString)
}
}

$ scala-2.10.0-M7/bin/scalac Test.scala
$ scala-2.10.0-M7/bin/scala Test

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 2, 2012

Imported From: https://issues.scala-lang.org/browse/SI-6306?orig=1
Reporter: Mikael Taina (tainami)
Affected Versions: 2.10.0-M7
Other Milestones: 2.10.0

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 4, 2012

@som-snytt said:
I just wanted to take some heat off of Try. AnyVal._ lose their func wrappers.

object Min {
  def f[A](a: =>A) = println(a.toString)
  def main(args: Array[String]) {
    f((1).toString)
    f((1).##)
  }
}
[[syntax trees at end of                   uncurry]] // simple-byname.scala
package badbyname {
  object Min extends Object {
    def <init>(): badbyname.Min.type = {
      Min.super.<init>();
      ()
    };
    def f[A >: Nothing <: Any](a: () => A): Unit = scala.this.Predef.println(a.apply().toString());
    def main(args: Array[String]): Unit = {
      Min.this.f[String](1.toString());
      Min.this.f[Int](1.##())
    }
  }
}
@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 4, 2012

@Blaisorblade said:
AnyVal is not needed in fact - the problem seems to appear on naked type variables with whatever bound, as shown in the below testcase:

object Min {
  //Don't work
  def f[A](a: =>A) = println(a.toString)
  def f1[A <: AnyVal](a: =>A) = println(a.toString)
  def f2[A <: AnyRef](a: =>A) = println(a.toString)
  def f2a[A <: String](a: =>A) = println(a.toString)
  //Works
  def f3[A](a: =>Seq[A]) = println(a.toString)
  def main(args: Array[String]) {
    f3(Seq(1))
    f3(Seq())
    f((1).toString)
    f((1).##)
    f1((1).##)
    f2((1).toString)
    f2a((1).toString)
  }
}
@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 4, 2012

@jrudolph said:
I would have guessed that I caused that with scala/scala@00a648b which was a fix for #1247. But it seems this bug seems to be present in 2.10.0-M1 as well.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 4, 2012

@jrudolph said:
It's the erasure phase which is introducing the cast.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 4, 2012

@jrudolph said:
But I guess it's just introducing the cast because the lifting to Function0 from uncurry is missing (I think, that's what Paolo meant with "lose their func wrappers"). As Paolo mentioned this happens only for .toString, .##, and .hashCode calls. Extra points if you find others.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 4, 2012

@retronym said:
In this commit, the tree Select(Const(1), "toString") is considered safe to inline.

scala/scala@fa2deeb#L1R84

This seems to trigger a long latent bug in Uncurry:

https://github.com/scala/scala/blob/v2.10.0-M7/src/compiler/scala/tools/nsc/transform/UnCurry.scala#L215

But I'm not sure yet what should go there instead.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 4, 2012

@retronym said:
Bonus points, please:

scala210 -nocompdaemon -e "def foo[A](a: => A) = a; foo(1.getClass())"
java.lang.ClassCastException: java.lang.Class cannot be cast to scala.Function0
	at Main$$anon$1.<init>(scalacmd4632653116387645739.scala:1)
@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 4, 2012

@som-snytt said (edited on Sep 4, 2012 10:49:34 PM UTC):
Community spirit badge if the PR fixes the comment Note that this is not called "isExprSafeToInline" to Note that this is not called "isPureExpr".

Kind of a "ceci n'est pas une pipe" moment. I read that in the middle of the night and stopped blinking for an indeterminate length of time.

https://github.com/scala/scala/blob/v2.10.0-M7/src/reflect/scala/reflect/internal/TreeInfo.scala#L70

I think, that's what Paolo meant with "lose their func wrappers".
It was. It's a little known and infrequently mulled fact that my middle name is Paul. And full disclosure, in that comment, I almost wrote, "funky wrappers."

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 5, 2012

@Blaisorblade said:
I retract my comment above, I debugged the wrong thing.
@jason: deEta, the code you mention, seems to change the type of the result. A comment should explain when it's supposed to work. If it never does, it should be removed, but assuming that it works correctly in some cases, a very minimal attempt for the fix can be found here:
https://github.com/Blaisorblade/scala/tree/issue/6306

It does work on the testcase, but it seems overkill; I add a set named inByNameCallSite analogously to byNameArg, but I'm not sure if I could just use byNameArg because I can't fully read the code; I currently suspect that I couldn't.

If this becomes a pull request, I'll add proper acknowledgments to everybody involved.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 5, 2012

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Sep 13, 2012

@Blaisorblade said (edited on Sep 13, 2012 1:54:50 PM UTC):
Pull request 1255 was finally merged, so I'm closing this bug.

@scabug scabug closed this Sep 13, 2012
@scabug scabug added the critical label Apr 7, 2017
@scabug scabug added this to the 2.10.0-M7 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
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.