Why does `as? TArgument` give an `Unchecked cast` ...
# announcements
k
Why does
as? TArgument
give an
Unchecked cast
warning
s
this question needs some more context in order to be answered precisely
k
This is the function
Copy code
fun <TArgument:Any> ArgumentParser<TArgument>.value(): TArgument?{
	return arguments[this] as? TArgument
}
I thought
as?
was a safe cast?
k
You can't actually safe cast to generics on the JVM because of erasure.
That's what "unchecked cast" means: https://stackoverflow.com/a/262539/5517612
s
But
as?
should safely return
null
if the cast fails
s
that’s not what that means
s
https://kotlinlang.org/docs/reference/typecasts.html
To avoid an exception being thrown, one can use a safe cast operator as? that returns null on failure
k
That function gets compiled to:
Copy code
fun ArgumentParser<Any?>.value(): Any?{
    return arguments[this]
}
That's what erasure means. How could it possibly check anything about
TArgument
? It doesn't even know about it.
s
Ha!!!! I read
TArgument
as a type, not as a generic type. Thanks!
🙃 1
@Kroppeb The warning is not about the
as?
but about the return-type vs the type that is actually returned. 🙂
k
?
It's only marking that piece of code
the
as? TArgument
The thing is that I know that the value will be TArgument if the key is in the dict, but there is no way to tell this to the compiler, right? The dictionary maps
ArgumentParser<T> -> T
s
You’ll have to remove the type-erasure to be sure the return type matches the value returned from
arguments[this]
. Make the type reified:
Copy code
inline fun <reified TArgument:Any> ArgumentParser<TArgument>.value(): TArgument? { ... }
k
Yes, your code could very well be correct, the warning is saying that you have to make very sure that you're right, because not only is compile-time safety broken (which is always the case for casts) but even the runtime can't check your cast because it's a generic type! This can introduce very hard to catch bugs.
💯 1
k
But then
arguments
has to be public no?
s
yup.
k
Or use
@PusblishedApi
.
k
?
s
@PublishedApi
doesn’t work on
private
, only on
internal
scope…
k
But if you're sure this cast is correct feel free to suppress it, that's quite common when writing your own datastructures. There's no real need for
reified
.
d
There is a bug report about this. as? On a type parameter is the same as
as
on a type parameter.
k
(it still checks the bound so it's not exactly the same (I know I'm being pedantic))
d
Wait, what's the difference?
k
For example:
Copy code
fun <T: Any> foo() {
    null as? T  //succeeds
    null as T   //fails
}