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

isInstanceOf/asInstanceOf support for parametric polymorphism (manifest doesn't help and turns of unchecked warning which makes it worse) #5042

Closed
scabug opened this issue Sep 29, 2011 · 3 comments
Assignees

Comments

@scabug
Copy link

scabug commented Sep 29, 2011

At the moment isInstanceOf/asInstanceOf don't support (upper bounded) type parameters so it parametric polymorphism is not possible even if the type parameter has a manifest. All the manifest does is turning unchecked warnings off, there is still a class cast exception which is why a manifest solution makes the problem even worse.

In C# you can do just this and it works:

if (e is E) call((E)e);

but in Scala you cannot do this even with a typeparameter with manifest:
if (e.isInstanceOf[E]) call(e.asInstanceOf[E])

Work around 1

if(isE(e) call(asE(e))
final def isE[F <: Exp: Manifest](e: F) = { manifest[E] <:< manifest[F] }
final def asE(e: Exp) = { val x = manifest[E].erasure.cast(e); println(x.getClass); x.asInstanceOf[E] }

is only turning of the unchecked warnings in hackish way

Work around 2

if (manifest[E].erasure.cast(e).isInstanceOf[E]) call(manifest[E].erasure.cast(e).asInstanceOf[E])

brings the unchecked warning it back so it is circular

Both workarounds generate a class cast exception so a manifest doesn't help much:
java.lang.ClassCastException: Cannot cast impl.Lit to extension.EvalExp

See enclosed:
expressionproblem.cs
expressionproblem.scala

@scabug
Copy link
Author

scabug commented Sep 29, 2011

Imported From: https://issues.scala-lang.org/browse/SI-5042?orig=1
Reporter: DaveScala (davescala)
Affected Versions: 2.9.1
Attachments:

@scabug
Copy link
Author

scabug commented Feb 10, 2012

@paulp said:
No unchecked warnings, prints -5. You appear to have multiple misapprehensions about how things work at runtime. You're never calling getClass on an instance whose type neither the compiler nor you know; from such beginnings one cannot be too surprised at CCEs.

diff --git a/expressionproblem.scala b/expressionproblem.scala
index fe31f7037d..55d30688dc 100644
--- a/expressionproblem.scala
+++ b/expressionproblem.scala
@@ -11,8 +11,10 @@ package exprframework {
 
     abstract class Node[V <: Visitor: Manifest] extends Exp { 
         final def handle(v: Visitor) {
-            if (manifest[V].erasure.cast(v).isInstanceOf[V]) accept(manifest[V].erasure.cast(v).asInstanceOf[V])
-            else v.default(this)
+            if (manifest[V].erasure isAssignableFrom v.getClass)
+              accept(v.asInstanceOf[V])
+            else
+              v.default(this)
         }
         //final def isV[W <: Visitor: Manifest](v: W) = { manifest[V] <:< manifest[W] }
         //final def asV(v: Visitor) = { val x = manifest[V].erasure.cast(v); println(x.getClass); x.asInstanceOf[V] }
@@ -21,8 +23,10 @@ package exprframework {
 
     abstract class Op[E <: Exp: Manifest] extends Visitor { 
         final def apply(e: Exp) {
-            if (manifest[E].erasure.cast(e).isInstanceOf[E]) call(manifest[E].erasure.cast(e).asInstanceOf[E])
-            else e.handle(this)
+            if (manifest[E].erasure isAssignableFrom e.getClass)
+              call(e.asInstanceOf[E])
+            else
+              e.handle(this)
         }
         //final def isE[F <: Exp: Manifest](e: F) = { manifest[E] <:< manifest[F] }
         //final def asE(e: Exp) = { val x = manifest[E].erasure.cast(e); println(x.getClass); x.asInstanceOf[E] }

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

scabug commented Feb 11, 2012

DaveScala (davescala) said:
Thanks, that works and I even found a shorter one:

manifest[V].erasure isAssignableFrom v.getClass

can be written as

manifest[V].erasure.isInstance(v)

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