elizarov
01/30/2017, 7:41 AMeladkay
06/03/2024, 2:26 PMSam
06/03/2024, 2:32 PMhho
06/03/2024, 2:53 PM!! already enough to break soundness? It makes stuff compile which normally shouldn't…eladkay
06/03/2024, 2:55 PMeladkay
06/03/2024, 2:56 PM!!, I guess that counts as much as "1 as String" counts. !! is an explicit cast which may fail, which is what we want. The problem is if !! converted the type T? of its operand to T in an unchecked way, allowing it to crash latereladkay
06/03/2024, 2:58 PM!! is an operator from T? to T, in this sense, null!! operates legally as expected: it throws a type errorhho
06/03/2024, 3:15 PM// JAVA
class Demo {
static String provideNull() {
return null;
}
}
// Kotlin
fun main() {
println(Demo.provideNull().length)
}eladkay
06/03/2024, 3:27 PMDemo.provideNull() is not String but String! , and there's an implicit cast there to String before accessing `String`'s length propertyrobstoll
06/03/2024, 8:43 PMeladkay
06/04/2024, 7:41 AMJason5lee
06/05/2024, 3:30 PMeladkay
06/05/2024, 3:39 PMRoukanken
06/06/2024, 2:23 PMMutableList extends List, which would lead one to assume that MutableList is subtype of List (and therefore check List<E> is MutableList<E> is safe, regardless of what is E, or where it comes from), but this isn't actually true from type theory standpoint.
To give concrete examples, take two concrete types, of which one is supertype of other - such as Any and Int, and draw a graph of types when you apply them to both list types. You get something like this, where A -> B means "A is supertype of B". Supertype relation can be looked upon as "A less concrete type than B", meaning that whatever you can do with A, you need to be able to do with B.
But from the graph drawn, there is one arrow missing for this to be true: MutableList<Any> is not supertype of MutableList<Int>, but over in the world of Lists this is true.
This causes the issue with the linked code - if you infer E to be Any, the code typechecks and is looks completely correct - element is String, so it's Any, this is MutableList<Int> so it's List<Any>, and MutableList<Any> is subclass of List<Any> so it makes sense that you can ask the is MutableList<Any> - but that question wouldn't be allowed if you still thought that this is MutableList<Int>. You somehow gained ability to do a new possible operation on it, via upcasting it... (And for completness, you can definitely store element: Any in MutableList<Any> )
TL;DR: List is weird, and both of these statements are true:
• For any given & concrete E , List<E> is supertype of MutableList<E>
• List is not supertype of MutableListeladkay
06/06/2024, 3:41 PM