to you call it, compiler needs to know, what type T is.
T is not used for any of the parameters, so it cannot be inferred from types of passed arguments.
In such case you need to provide it yourself in some other way.
T is used as return type, so it can be infered from the type of variable it is assigned to.
You can observe that in your working example:
val t: T = fetch(id.id ?: throw Exception("Id is unset for $id"))
However, if the type of variable is not defined explicitly, compiler again has not enough information to infer the type:
val t = fetch(id.id ?: throw Exception("Id is unset for $id")) // does not compile
In your not working example, the method is called as part of an expression.
In this case we could not use any of the mentioned ways to provide the type.
However, we can always define it explicitly in angle brackets:
return fetch<T>(id.id ?: throw Exception("Id is unset for $id"))
.also { id.obj = it } // Compiles!
Well, I guess potentially it could be possible for compiler to support it, but I don’t know any technical details.
You may submit a request to kotl.in/issue.