Should this be allowed? It does compile fine if I ...
# getting-started
b
Should this be allowed? It does compile fine if I remove the type annotation from
acceptsString
I want to say
R
can be constrained to
String
by the smart cast but I'm not sure.
Copy code
interface Accepts<in T> {
    fun accept(value: T)
}

object AcceptsString : Accepts<String> {
    override fun accept(value: String) = println(value)
}

fun <R> example(providesR: () -> R, acceptsR: Accepts<R>) {
    if (acceptsR is AcceptsString) { // so R must be String
        val acceptsString: AcceptsString = acceptsR
        val providedR = providesR()

        acceptsString.accept(providedR)
        //                   ^^^^^^^^^ Type mismatch.
        //                             Required: String
        //                             Found: R
    }
}
d
Yes that's looks correct to me. That should indeed be a compiler error.
AcceptsString
can't take
R
.
b
I guess I'm wondering if it's guaranteed safe for me to do
acceptsString.accept(providedR as String)
in this case. (And if so, could Kotlin in the future be made to infer
R
as
String
here)
d
What does safe mean? If
R
is not a
CharSequence
an exception will be thrown if you do that.
Might be possible in the future with contracts or something.
b
(I just realized I forgot to change
CharSequence
types back to
String
in the example after playing around, so fixed that in a code block)
If
R
is not a
String
an exception will be thrown if you do that.
That's the thing, I don't think it's possible for
R
to be anything other than a
String
within that if block
And I'm definitely not certain, but I think the fact that the example compiles fine without the
: AcceptsString
is proof of that
d
It shouldn't be possible ideally but type erasure is very much a thing on the JVM.