So, most people were wrong about this, and it also split opinion rather evenly... I suspect even that some of the people who were right were right for the wrong reasons! But the Scala compiler is actually being safe and correct, here. Explanation below...https://twitter.com/propensive/status/1284952925727580165 …
-
Show this thread
-
The scrutinee, which is the value `List(0)` has the runtime type `List[_]` or `List[T] forSome { type T }` but the static type, `Seq[Int]`. There's no available information about the List's element type at runtime without inspecting an actual value, such as its head.
1 reply 0 retweets 2 likesShow this thread -
For the first case clause, the compiler will generate bytecode which checks whether the scrutinee has the correct runtime type to match, which is like asking, `scrutinee.isInstanceOf[List[_]]`. That returns true for any List, so it matches at runtime, and we get the value `1`.
1 reply 0 retweets 3 likesShow this thread -
But a lot of people expected a warning about the type parameter. But it's provably not necessary. If the runtime type test has passed, the compiler knows *for that branch* that the scrutinee is a subtype of List[_] and statically that it is a subtype of Seq[Int].
1 reply 0 retweets 1 likeShow this thread -
If something is a subtype of `A` and a subtype of `B`, then it is a subtype of `A with B`, the greatest lower-bound of `A` and `B`, or in this case, `List[_] with Seq[Int]`. It might be obvious how that could be simplified, but maybe not so obvious why.
1 reply 0 retweets 2 likesShow this thread -
Type intersection (`with`) takes an *intersection* of the instances of each type, but defines a type which is the *union* of the properties of those types. Properties and instances of types are duals!
1 reply 0 retweets 2 likesShow this thread -
So `List[_] with Seq[Int]` is the union of the properties of `List[_]` with the properties of `Seq[Int]`. Noting that `List[T] <: Seq[T]` and that both types are covariant, the compiler can deduce that `List[_] with Seq[Int]` simplifies to `List[Int]`.
1 reply 0 retweets 3 likesShow this thread -
That means that the runtime test, combined with the static type, is sufficient for Scala to be certain that the scrutinee is not just a `List[_]` but a `List[Int]`. No warning is necessary. The covariance of `List` would allow us to safely match against, say, `List[AnyVal]` too.
1 reply 0 retweets 2 likesShow this thread -
So, Scalac is spot on here, and not by luck, but by carefully following several nontrivial logical steps as a constraint solver. So, maybe we should have a bit more trust that it's doing the right thing, next time! ;)
1 reply 0 retweets 14 likesShow this thread -
Replying to @propensive
Very interesting Jon! Thank you for that. Wouldn't be possible for scalac to warn that the second case is dead code here?
1 reply 0 retweets 0 likes
The information is all there, but the type ascription of Seq[Int] is an explicit instruction to the compiler not to use it, so it shouldn't...
Loading seems to be taking a while.
Twitter may be over capacity or experiencing a momentary hiccup. Try again or visit Twitter Status for more information.