David Kubecka
03/09/2023, 11:56 AM@Nullable which is overly pessimistic?
For example, I want to create a shortcut for transactions execution:
fun <T> PlatformTransactionManager.execute(block: () -> T): T =
TransactionTemplate(this).execute { _ -> block() }
This doesn't compile because execute is marked as @Nullable, therefore the return type must be T?. Instead would like it to be T, that is whatever block returns (which might also be null).Rob Elliot
03/09/2023, 11:59 AMfun <T> PlatformTransactionManager.execute(block: () -> T): T =
TransactionTemplate(this).execute { _ -> block() } ?: throw IllegalStateException("Expected it to be impossible for execute to return null")David Kubecka
03/09/2023, 12:00 PMRob Elliot
03/09/2023, 12:00 PMRiccardo Lippolis
03/09/2023, 12:09 PMfun <T> PlatformTransactionManager.execute(block: () -> T): T =
TransactionTemplate(this).execute { _ -> block() } as T
this appears to be working, and it removes the warningDavid Kubecka
03/09/2023, 12:13 PMRiccardo Lippolis
03/09/2023, 12:17 PMRiccardo Lippolis
03/09/2023, 12:22 PMephemient
03/09/2023, 12:24 PMas T,
@Suppress("UNCHECKED_CAST")Riccardo Lippolis
03/09/2023, 12:31 PMDavid Kubecka
03/09/2023, 12:37 PMkqr
03/09/2023, 12:39 PMT ?David Kubecka
03/09/2023, 12:40 PM<T> doesn't say anything about its nullability (in contrast to e.g. <T : Any> )kqr
03/09/2023, 12:45 PMDavid Kubecka
03/09/2023, 12:46 PMT and T?. Well, T in this case means the exact return type of the block (preserving nullability), while T? might not preserve the nullability, i.e. even if block returned non-null then TransactionTemplate#execute might still return null.
I guess that's a principal deficiency of those java annotations.Riccardo Lippolis
03/09/2023, 1:44 PMWeird indeed. Does it compile without warnings? (btw I also use IDEA)yes, no compiler warnings as well... I use Kotlin 1.8.10, btw
deive
03/09/2023, 5:04 PM!! ?
fun <T> PlatformTransactionManager.execute(block: () -> T): T =
TransactionTemplate(this).execute { _ -> block() }!!Rob Elliot
03/09/2023, 5:05 PMdeive
03/09/2023, 5:07 PMTransactionTemplate.execute returns T? but you are always running block: () -> T then TransactionTemplate(this).execute { _ -> block() }!! should be OK?Rob Elliot
03/09/2023, 5:08 PMval x: String = tm.execute { "not null" }
val y: String? = tm.execute { if (Random.nextInt(2) == 1) "not null" else null }ephemient
03/09/2023, 5:09 PM<T> is neither nullable nor non-nullable) and Kotlin (where there is such a distinction)ephemient
03/09/2023, 5:13 PM@Nullable <T> T foo() becomes Kotlin fun <T> foo(): T?, Java @NonNull <T> T foo() becomes Kotlin fun <T> foo(): T & Any, and <T> T foo() can't be written directly in Kotlin due to platform nullability. none of them result in fun <T> foo(): Tdeive
03/09/2023, 5:25 PMblock returns (which might also be null)." - this means that block will have to return T? so what I said was moot!Rob Elliot
03/09/2023, 5:26 PMT. Whether or not `T`'s concrete type is nullable depends on how you define the block.Rob Elliot
03/09/2023, 5:27 PMval notNullBlock: () -> String = { "not null" }
val x: String = tm.execute(notNullBlock)
val nullableBlock: () -> String? = { if (Random.nextInt(2) == 1) "not null" else null }
val y: String? = tm.execute(nullableBlock)deive
03/09/2023, 5:30 PMPlatformTransactionManager.execute to be fun <T : Any> for a non-nullable version?Rob Elliot
03/09/2023, 5:30 PMdeive
03/09/2023, 5:30 PMRob Elliot
03/09/2023, 5:32 PM