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
array pattern must respect array invariance #3968
Comments
Imported From: https://issues.scala-lang.org/browse/SI-3968?orig=1 |
@paulp said: I became uncertain and verified with the specification that this should not match. It seems pretty clear that it should not. First, unlike arrays in Java or C#, arrays in Scala are not co-variant; That is, S <: T does not imply Array[S] <: Array[T ] in Scala. However, it is possible to cast an array of S to an array of T if such a cast is permitted in the host environment.
For instance Array[String] does not conform to Array[Object], even though String conforms to Object. However, it is possible to cast an expression of type Array[String] to Array[Object], and this cast will succeed without raising a ClassCastException. Example: I believe I know how to fix it, and I will now investigate this belief. |
@paulp said: case x: Array[AnyRef] => to catch everything but the primitive arrays. So assuming that shouldn't match, what would we like to replace it with? The problem is that this: case x: Array[_] => Does not give you an Array[AnyRef] on the right hand side, so you end up with lots of currently unnecessary casts. It looks like a bug that: case x: Array[_ <: AnyRef] => doesn't work (it says "not found: type _$$1" or thereabouts.) However this seems to work, although I haven't properly tested. I can't get it to compile without defining an alias. type AnyAnyRef = T forSome { type T <: AnyRef }
case x: Array[AnyAnyRef] => ... |
@paulp said: http://github.com/scala/scala/commit/927db662c607160bdc8ddb17dd96637516bcd821 The test case it passes: |
@adriaanm said: |
@paulp said:
OK, thanks for the info. As a point of interest this appears to have been the true cause of various confusions we experienced regarding the necessity of matchesPattern etc. |
@adriaanm said: even if we did make a u-turn onto the high road, the worry is we'd be stuck in reflection traffic |
@paulp said:
I think this needs further consideration. Can we use spec citations? I missed the oath apparently.
I can't see how it's a u-turn. The example above doesn't now and hasn't ever said unreachable code. But if we intentionally match covariantly it remains trivial to create runtime failures. How is it any different in effect to have Array[String] match as Array[AnyRef] in a pattern match than it is to allow Array[String] as an argument to an Array[AnyRef] parameter type? I can't see any point in making arrays behave invariantly everywhere else and then leaving open this huge hole for runtime failure. (Array[String]("a"): Any) match { case x: Array[AnyRef] => x(0) = new AnyRef }
java.lang.ArrayStoreException: java.lang.Object And if we're really going to make matching work right wrt type parameters when a manifest is available, we have this fairly ridiculous situation where the erased types match correctly and the type which actually reified the relevant type information has that information discarded and leads to a runtime failure. |
@paulp said: |
@paulp said: A parameterized type pattern scala.Array[T1], where T1 is a type pattern. This type pattern matches any non-null instance of type scala.Array[U1], where U1 is a type matched by T1. |
@paulp said: |
@soc said (edited on Dec 1, 2011 8:04:09 PM UTC): scala -Yvirtpatmat
Welcome to Scala version 2.10.0.r26093-b20111130020250 (OpenJDK 64-Bit Server VM, Java 1.7.0_147-icedtea). Results in: scala> Test.main(null)
3
3 This got worse, didn't it? Update: Weird, same behavior also with the old patter matcher ... is this a regression? |
@adriaanm said: |
@adriaanm said:
"where U1 is a type matched by T1" should really read "where a value of type U1 is matched by the type T1"
I agree all of these are worthwhile, but I don't think I can do this in time for 2.10.0. |
@gkossakowski said: |
Since it is not going down without a fight, ticket time. Adriaan observed that Array matching is being done covariantly. So is isInstanceOf it turns out. The following prints "1 1" but should print "2 2".
The text was updated successfully, but these errors were encountered: