Richard Gomez
12/01/2021, 9:53 PMcompiles
method compiles without issue, but if I save the expression to a variable instead of returning it, it complains about a type mismatch.Response
, but it needs to be RestResponse because that allows you to set status code, headers, etc.
// Both of these work
@GET
fun compiles2(): Response {
return if (dto != null) dto
else ErrResponse("baz")
}
@GET
fun compiles3(): Response {
val response = if (dto != null) dto
else ErrResponse("baz")
return response
}
Casey Brooks
12/01/2021, 10:05 PMcompiles()
method, the compiler knows the return type of the function, and so it can check whether the generic RestResponse
returns the specific type of the function, and indeed it does. There is no type inference in here, just simple type-checking.
In fails()
, the compiler must first infer the type of the response
variable, and since the RestResponse
is (I'm assuming) a Java class, it tries to reconcile the Java generic variance with Kotlin, and determines it to have out
variance. But the fails()
function itself does not have that variance, which is why it won't compile. Adding a type-hint might help the compiler infer the type correctly (val response: RestResponse<Response> = ...
)Richard Gomez
12/01/2021, 10:06 PMInThat's a good guess, and what I was initially thinking, but I don't think it's specific to Java. The error persists even when I use a Kotlin 'mock' of RestResponse., the compiler must first infer the type of thefails()
variable, and since theresponse
is (I'm assuming) a Java class, it tries to reconcile the Java generic variance with Kotlin, and determines it to haveRestResponse
variance.out
data class RestResponse<T>(val status: Int, val entity: T) {
companion object {
fun <T> ok(entity: T): RestResponse<T> = RestResponse(200, entity)
fun <T> status(status: Int, entity: T): RestResponse<T> = RestResponse(status, entity)
}
}
(Adding an explicit type hint does work though)ilya.gorbunov
12/02/2021, 5:28 AMRestResponse<Ok>
and RestResponse<Error>
and assign them to RestResponse<Response>
even though Ok
and Error
are subtypes of Response
RestResponse<Response>
, it can infer types of RestResponse.ok
and RestResponse.status
invocations as
ok<Response>(...)
and status<Response>(...)
, so the result will be assignable to RestResponse<Response>
.RestResponse<out Response>
Richard Gomez
12/05/2021, 10:36 PM