e.g. ```fun <T> bar(): T { error("") ...
# getting-started
m
e.g.
Copy code
fun <T> bar(): T { 
    error("")
    return "" as T
}

fun foo() {
    if (true) {
        1
    } else {
        bar()
    }
}
This works - bar can be invoked, because it infers to int. But if you unwrap the if statement, suddenly the return type of bar can't be inferred anymore (the contents of bar aren't important here, this crops up no matter what it contains).
r
Presumably in the real world bar accepts a
T
as an argument, otherwise there's no point in it being generic... have you got a real world example?
m
Real world example is nearly the same, it uses an inlined reified function to change its behaviour based on return type.
Problem occurs without inline/reified, though, so it seems a distraction.
r
Not a distraction - a reified type is basically an argument to the function.
I don't think the compiler can safely just assume that you want
Unit::class
to be the argument to that function.
m
In what situations would the inference be invalid (in the unwrapped example I mean)
r
Without seeing the function it's hard to say, because it will depend on how you are using
T::class
. But you could, for instance, be sending the value
T::class.simpleName
over the wire, or anything really. It would be extremely surprising if
val x: Int = bar()
did one thing, but
bar()
by itself did something quite different.
m
In this case the behavior is not all that surprising because it's returning the same underlying "thing" in different formats, so it can be seen as a kind of 'data cast'. But yeah I guess this is something the compiler just can't do.
a
Hm. IMHO the
if
should return the type of the first common ancestor of
T
and
Int
, i.e.
Any
. A return of
Unit
means instead
foo()
is a total side effect, returning no value (so it needs not be concerned in any manner with providing a result in return). Since
if
is an expression (vs. a statement) it will produce a value of some type, and a value needs have a type.
Unit
means, rather, something along the lines of "there is no value--of any type--associated here". Expecting that a generic, i.e. a type variable associated to some value, will resolve to
Unit
, which means
no value
, perhaps is a misplaced expectation?
m
In this case the if is a distraction. It works fine with that, because "Any" is an acceptable inferred type there (means = don't care). The issue is the compiler error when there's no if
a
Help me understand: How would you code that?
m
if (T::class == Any::class) { ... discard result .. } else if (T::class == String::class) result.asString() else ....
a
I believe If you want to use code like that,
T
must be reified. But I am missing your point altogether, I'm afraid?
m
It's indeed reified. Nonetheless it fails sometimes, when the compiler could easily DWIM
The example above is deliberately simplified. It fails in the same way, reified or not.
Perhaps it was over-simplified 🙂