Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function returns generic class of base interface - Type mismatch

The second to last line doesn't compile but the last line compiles fine:

  • What is the reason (they seem equivalent to me)?
  • What can I change so that return if(true) m1 else m2 will compile?

Compile error:

Type mismatch: inferred type is Hold<HelloMsg> but Hold<Msg> was expected

interface Msg
class HelloMsg: Msg
class ByeMsg: Msg
class Hold<T: Msg>(val msg: T)

fun test(): Hold<Msg> {
  val m1 = Hold(HelloMsg())
  val m2 = Hold(ByeMsg())
  return if(true) m1 else m2                             //DOESN'T COMPILE
  return if(true) Hold(HelloMsg()) else Hold(ByeMsg())   //COMPILES
}
like image 590
assylias Avatar asked Jun 06 '26 00:06

assylias


1 Answers

What can I change so that return if(true) m1 else m2 will compile?

Make Hold covariant: class Hold<out T: Msg>(val msg: T). Then Hold<HelloMsg> and Hold<ByeMsg> will both be subtypes of Hold<Msg>.

I think I have the answer to my second question: fun test(): Hold<out Msg> { ... }

Yes, that works too, but more locally. class Hold<out T> is basically equivalent to making all uses of Hold marked with out.

What is the reason (they seem equivalent to me)?

In the if(true) m1 else m2 case the types of m1 and m2 are already fixed by their declaration and different from Hold<Msg>.

In the if(true) Hold(HelloMsg()) else Hold(ByeMsg()) the compiler is typing Hold(HelloMsg()) while knowing it has to be Hold<Msg>. So it infers the type parameter as Hold<Msg>(HelloMsg()). Same with the other branch.

like image 138
Alexey Romanov Avatar answered Jun 09 '26 12:06

Alexey Romanov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!