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

Casting of AnyVal types behaves differently based on compile time type #1448

Open
scabug opened this issue Oct 25, 2008 · 17 comments
Open

Casting of AnyVal types behaves differently based on compile time type #1448

scabug opened this issue Oct 25, 2008 · 17 comments
Milestone

Comments

@scabug
Copy link

scabug commented Oct 25, 2008

Consider the following examples:

scala> 1L.asInstanceOf[Int];
res8: Int = 1

scala> (1L : Any).asInstanceOf[Int];
java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer
	at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source)
	at .<init>(<console>:5)
	at .<clinit>(<console>)
	at RequestResult$$.<init>(<console>:3)
	at RequestResult$$.<clinit>(<console>)
	at RequestResult$$result(<console>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.Nati...

It seems that when you cast AnyVals of known types between eachother the compiler turns them into numeric conversions as with Java. However if you cast an Any to an AnyVal subtype it does not perform these conversions. This seems like very inconsistent behaviour to me (It's also counter to the specced behaviour).

There are two possible fixes here:

  • Remove the behaviour for performing numeric conversion on casts so that the first example would throw a ClassCastException.
  • Change the methods on BoxesRuntime such as unboxToInt so that they cast to Number instead of the appropriate numeric type. This way the same numeric conversions will be applied when you cast an arbitrary type to a value type.

I strongly prefer the former (in particular it's what the spec says should happen). I suspect the latter is the one that will annoy people the least.

@scabug
Copy link
Author

scabug commented Oct 25, 2008

Imported From: https://issues.scala-lang.org/browse/SI-1448?orig=1
Reporter: @DRMacIver

@scabug
Copy link
Author

scabug commented Oct 26, 2008

@DRMacIver said:
I've been looking at some of the code the pattern matcher generates. I think it will break if we go with the first option. :-(

I still think the first option is technically the correct one. But it probably requires a lot of code to be fixed.

@scabug
Copy link
Author

scabug commented Oct 28, 2008

@odersky said:
we probably need to make a special case for numeric casts in the spec

@scabug
Copy link
Author

scabug commented Dec 19, 2013

@gzm0 said:
As a note aside (2.10.2 and 2.11.0-M7)

scala> 1L.isInstanceOf[Int]
res0: Boolean = false

@scabug
Copy link
Author

scabug commented Dec 19, 2013

@retronym said:
Spec:

The test x.asInstanceOf[T] is treated specially if T is a numeric value type (§12.2). In this case the cast will be translated to an application of a conversion method x.toT (§12.2.1). For non-numeric values x the operation will raise a ClassCastException.

@scabug
Copy link
Author

scabug commented Dec 19, 2013

@gzm0 said (edited on Dec 20, 2013 9:29:44 AM UTC):
As discussed in core meeting, will try to convert casts on boxed types to casts to asInstanceOf[Number].longValue() (as opposed to asInstanceOf[java.lang.Long])

@scabug
Copy link
Author

scabug commented Dec 20, 2013

@gzm0 said:
Example fix: scala/scala#3294

@scabug
Copy link
Author

scabug commented Dec 21, 2013

@gzm0 said:
Alternative fix (deprecates conversion by casting): scala/scala#3295

@scabug
Copy link
Author

scabug commented Dec 21, 2013

@paulp said:
I tried and failed to get rid of conversion by casting years ago in #4437.

@scabug
Copy link
Author

scabug commented Dec 22, 2013

@gzm0 said:
Thanks for the pointers, Paul. I don't see how this prevents us from fixing at least the casts on numbers which are non-null. But it is true that Scala's null semantics seem pretty much broken.
Being a young, naive and still motivated Scala hacker, I haven't lost hope we can fix that. I try to do some thinking and post in #4437. Any additional comments or pointers to use cases and thoughts are welcome.

@scabug
Copy link
Author

scabug commented Dec 23, 2013

@paulp said:
"I don't see how this prevents us from fixing at least the casts on numbers which are non-null."

In the first comment martin says "We need to leave asInstanceOf as an operation that can cast an Any to a numeric type." I don't know if your quote means you didn't see the comment or that you don't yet know why this is sufficient to prevent you from fixing it.

@scabug
Copy link
Author

scabug commented Dec 23, 2013

@paulp said:
God damn it, I accidentally replied to a comment by editing the comment and I don't know any way to recover it. Thanks jira. I deleted the whole thing since it made no sense to reply to something I'd deleted in the process of replying to it. My apologies.

@scabug
Copy link
Author

scabug commented Dec 23, 2013

@paulp said:
Okay, thanks to retronym I can reconstruct, possibly with some mangling. Tobias's comment which I accidentally deleted:

Thanks for your feedback and taking the time.

asInstanceOf will always be able to cast an Any to a numeric type, but only to the "right" numeric type. Martin has asked me to "fix" this issue by allowing conversion also on boxed versions. You can find the fix in scala/scala#3294

The problem is that it requires an additional instanceof check for every (!) unboxing operation since we also have to convert java.lang.Character which don't extend java.lang.Number.

Further, most of the concerns raised about disallowing casts for conversion were about breaking code. scala/scala#3295 (and comments) shows that we can properly deprecate such code and that it can easily be adapted (even the compiler just rewrites asInstanceOf[T] to toT).

@scabug
Copy link
Author

scabug commented Dec 23, 2013

@paulp said:
To which I replied:

shows that we can properly deprecate such code and that it can easily be adapted (even the compiler just rewrites asInstanceOf[T] to toT).

Okay, but that was obvious from the beginning. I'm not sure if you're reading between the lines here or what so I'll be clearer: martin settles these issues by fiat. If "martin has asked me to" means he has changed his stance offline, then you should articulate that clearly, because this isn't about the technical question.

@scabug
Copy link
Author

scabug commented Dec 24, 2013

@gzm0 said:
Paul, I'm sorry if it wasn't clear from what I wrote that this issue has been re-discussed (that is including Martin). I thought mentioning that we discussed this in the core meeting was sufficient, as Martin usually attends.

More clearly: Martin was especially concerned with the fact that this makes boxing observable and thinks this (i.e. this ticket) needs to be fixed. He therefore proposed to lift the casts in unboxing from asInstanceOf\[Int\] to asInstanceOf\[Number\] (the OP's second proposed option) and see if something blows up.

PR #3294 does this, nothing blows up, one additional instanceof is required. No feedback from Martin yet.

@scabug
Copy link
Author

scabug commented Dec 26, 2013

@paulp said:
It's been so long since I've heard anyone mention the "core meeting" I thought the "as discussed in the core meeting" line was an unattributed quote from meeting minutes somewhere 2008-2010.

@scabug
Copy link
Author

scabug commented Mar 11, 2014

@adriaanm said:
I believe this is no longer a spec issue, but a compiler one. The main reason the PR wasn't merged was that we didn't have time to convince ourselves the performance impact was acceptable.

@scabug scabug added this to the Backlog milestone Apr 6, 2017
@scala scala deleted a comment from scabug Feb 9, 2023
@scala scala deleted a comment from scabug Feb 9, 2023
@scala scala deleted a comment from scabug Feb 9, 2023
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

1 participant