https://kotlinlang.org logo
#codereview
Title
# codereview
s

stoyicker

10/26/2023, 1:17 PM
Hi, I'm trying to create a function which produces a value of a type parameter, which may or may not be nullable. This is what I have:
Copy code
private fun <T> runInTheFutureButAlsoWaitForResult(block: Foo.() -> T): T {
    var ret: T? = null
    var done = false
    val condition = reentrantLock.newCondition()
    someOtherThread.runAtSomePointInTheFuture {
        ret = delegate.block()
        done = true
        reentrantLock.withLock { condition.signal() }
    }
    reentrantLock.withLock {
        while (!done) {
            condition.await()
        }
    }
    return ret as T
}
While this does work at runtime for both cases in which T is nullable and non-nullable, casting ret to T is marked as unsafe, which does make sense, but if I define ret as type T, I can't assign null to it, which makes sense too, but I also can't assign anything else because I don't know what T is so I can't instantiate it. Therefore, I could try to make it lateinit, but mind you, lateinit can't be used with types whose upper bound is nullable, as is the case implicitly for T. Is there a way to write this code "correctly"?
h

hho

10/26/2023, 1:33 PM
I don't think I understand … If you have the nullable case, you have to make everything nullable, right?
Copy code
fun <T> runInTheFutureButAlsoWaitForResult(block: Foo.() -> T?): T? {
    …
    return ret
}
s

stoyicker

10/26/2023, 1:36 PM
no you don't have to. T implicitly inherits from Any?, so by specifying T you're saying "whatever the caller uses as type parameter, which may or may not be nullable". The problem is not with the method signature, but with the type of
ret
a

ascii

10/26/2023, 2:09 PM
I'd just suppress the unsafe warning
You own whatever block's code is, right? You could write tests to ensure it's not nullable.
s

stoyicker

10/26/2023, 2:11 PM
the thing is it might be nullable, and that does work at runtime, because T in "ret as T" is nullable. suppressing is of course an option, I was just thinking maybe there's a way that doesn't involve doing that
d

Daniel Pitts

11/08/2023, 2:02 AM
Heh, I ran into basically the same thing recently, and just ended up suppressing the
unsafe cast
complaint.
Note, your code here will deadlock if
delegate.block()
throws an exception.
s

stoyicker

11/08/2023, 9:02 AM
true that, thank you