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

Type checking error with simple evaluator #4818

Closed
scabug opened this Issue Jul 20, 2011 · 4 comments

Comments

Projects
None yet
2 participants
@scabug
Copy link

scabug commented Jul 20, 2011

After a discussion on #scala I put together a simple little expression evaluator using case classes:

https://gist.github.com/1094143

Function "eval" is correct, while function "badEval" is not, as it does not eval the input value to the function before passing it, meaning a Term[A] is being passed instead of an A.

I have tried running this gist using both Scala 2.9.0-1 and also the current trunk of scala/scala on github (commit e70f043d15a7ad759074), both throw a runtime exception when the gist is put through the scala REPL:

$ ./build/pack/bin/scala ~/GADT.scala
eval gives:25
java.lang.ClassCastException: Main$$anon$1$Val cannot be cast to java.lang.Integer
at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source)
at Main$$anon$1$$anonfun$1.apply(GADT.scala:22)
at Main$$anon$1.badEval(GADT.scala:18)
at Main$$anon$1.(GADT.scala:25)
at Main$.main(GADT.scala:1)
at Main.main(GADT.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:78)
at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:24)
at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:88)
at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:78)
at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:33)
at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:40)
at scala.tools.nsc.ScriptRunner.scala$tools$nsc$ScriptRunner$$runCompiled(ScriptRunner.scala:171)
at scala.tools.nsc.ScriptRunner$$anonfun$runScript$1.apply(ScriptRunner.scala:188)
at scala.tools.nsc.ScriptRunner$$anonfun$runScript$1.apply(ScriptRunner.scala:188)
at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1$$anonfun$apply$mcZ$sp$1.apply(ScriptRunner.scala:157)
at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1$$anonfun$apply$mcZ$sp$1.apply(ScriptRunner.scala:157)
at scala.Option.exists(Option.scala:188)
at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply$mcZ$sp(ScriptRunner.scala:157)
at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply(ScriptRunner.scala:131)
at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply(ScriptRunner.scala:131)
at scala.tools.nsc.util.package$.waitingForThreads(package.scala:34)
at scala.tools.nsc.ScriptRunner.withCompiledScript(ScriptRunner.scala:130)
at scala.tools.nsc.ScriptRunner.runScript(ScriptRunner.scala:188)
at scala.tools.nsc.ScriptRunner.runScriptAndCatch(ScriptRunner.scala:201)
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:58)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:80)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:89)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Jul 20, 2011

Imported From: https://issues.scala-lang.org/browse/SI-4818?orig=1
Reporter: Iain McGinniss (iainmcgin)
Affected Versions: 2.9.0
Other Milestones: 2.10.0

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Jul 20, 2011

@SethTisue said (edited on Jul 20, 2011 1:06:07 PM UTC):
minimized (I think):

trait Term[A]
case class Fn[A, B](f: A => B) extends Term[A => B]
case class Apply[A, B](fn: Term[A => B]) extends Term[B]
(Apply(Fn(identity[String])): Term[String]) match {
  case Apply(Fn(f)) => f(()) }

note that it doesn't matter what you pass to f. here I pass (), but you can pass anything at all and the compiler swallows it without complaining (!!!)

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Jul 21, 2011

@paulp said:
Mmm, that's pretty spectacularly broken. It's been like that forever too.

Simpler reproduction:

scala> case class Fn[A, B](f: A => B) ; def f(x: Any) = x match { case Fn(f) => f(5) } ; f(Fn((x: String) => x))
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
	at $anonfun$1.apply(<console>:12)
	at .f(<console>:10)
	at .<init>(<console>:12)

I think the inferred type should be Fn[Nothing => Any] and instead is inferring Fn[Any => Any], which of course means it's telling itself that it can be applied to anything. The contravariant parameter is not flipping the flippy bits.

Adriaan, what do you think?

@scabug

This comment has been minimized.

Copy link
Author

scabug commented May 25, 2012

@retronym said:
Fixed in 2.10.0-M3:

scala/scala#626

@scabug scabug closed this May 26, 2012

@scabug scabug added this to the 2.10.0-M3 milestone Apr 7, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment