kotlin
kotlin copied to clipboard
[JVM] Change ConcurrentMap.getOrPut from implicit Any! to Any
Why does Kotlin compiler let's this trap compile? I introduced an error in production today on my company because of this, I thought the compiler or the IDE would catch something like this, but apparently not.
ConcurrentHashMap<Int, String>().getOrPut(1) { null } // compiles just fine, but it'll throw in runtime mutableMapOf<Int, String>().getOrPut(1) { null } // compiler error: Null can not be a value of a non-null type String
This is because with ConcurrentMap<K, V>.getOrPut
the V
is implicitly Any!
, whereas with MutableMap<K, V>.getOrPut
it's Any
. Admittedly, this is a bit of a naive fix and will likely require some additional changes for cases where you actually want V: Any?
(I have to check if that's legal).
Currently, you can use null
as a key as well, I think you might have to make K : Any
too.
ConcurrentHashMap<Int, String>().getOrPut(null) { null } // compiles just fine, too
ConcurrentMap
does not restrict keys and values to non-null values so with your change means it no longer works for those cases which I assume is a no go for the kotlin team. Remember that null support of maps is something the sub type gets to decide.
I think you have better luck getting an additional function included:
public inline fun <K : Any, V : Any> ConcurrentHashMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V = ...
Citing the docs for ConcurrentHashMap:
* <p>Like {@link Hashtable} but unlike {@link HashMap}, this class
* does <em>not</em> allow {@code null} to be used as a key or value.