Understanding star projections of bound generic type


#1

I have a class declared as Query<out T : Any>. Then I have this method:

fun bindFoo(liveData: LiveData<Query<*>>) {...}

Let’s say I have val liveData: LiveData<Query<List<String>>> and I call the method like bindFoo(liveData):
I get a compiler error saying

Required:
LiveData<Query<*>>
Found:
LiveData<Query<List<String>>>

Docs say that:

For Foo<out T : TUpper> , where T is a covariant type parameter with the upper bound TUpper , Foo<*> is equivalent to Foo<out TUpper> .

I can’t really understand why the star projection is not allowed in this case. Isn’t List<String> a subtype of Any?

If I changed the method signature to:

fun <T : Any> bindFoo(liveData: LiveData<Query<T>>) {...}

then the compiler error goes away.

What am I missing?


#2

It depends on how LiveData is defined. If it’s just LiveData<T>, then it’s not covariant on its type parameter T. And because of that Query<List<String>> is not a subtype of Query<*>. If you want it to be covariant just define it as LiveData<out T>.


#3

Thank you. I finally see what I was missing, I was trying to resolve variance on a type parameter itself. LiveData is actually invariant on T, so now it’s all clear. Thanks for pointing it out!