-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixing Indeterminate Behavior Caused by InvocationKind.EXACTLY_ONCE
#106
base: master
Are you sure you want to change the base?
Conversation
Thanks for the PR. Please can you explain why
From my understanding, your description that "it is assumed that If it works as you described, then I don't see how anyone could ever write a contract that truly executes a function parameter Consider rewriting your example in the following format: private var value: Int = 0
fun throwableFunction() = throw RuntimeException()
fun throwSomething() {
throwableFunction()
value = 1
}
@Test
fun indeterminate() {
val value: Int
com.github.michaelbull.result.runCatching(::throwSomething)
assertEquals(
expected = 0,
actual = value,
)
} In the example above, |
Does that example picture compile without the contract? If we don't tell the compiler it will be executed at all with an |
The example with In @Test
fun try_finaly() {
val value: Int
try {
throwableFunction()
value = 1
} finally {
// No guarantee that `value = 1` was executed
assertEquals(
expected = 1,
actual = value, // Variable 'value' must be initialized
)
}
// Guaranteed that `value = 1` was executed
assertEquals(
expected = 1,
actual = value, // No Error
)
} When using To prevent the compiler from mistakenly assuming that the |
Looking at this: @Test
fun kotlin_runCatching() {
val value: Int
kotlin.runCatching {
throwableFunction()
value = 1 // Captured values initialization is forbidden due to possible reassignment
}
assertEquals(
expected = 1,
actual = value, // Variable 'value' must be initialized
)
} @Daiji256 -- is it possible you've misunderstood what So this example would be better written as something like: @Test
fun kotlin_runCatching() {
// value is Result<Int, Throwable>
val value = kotlin.runCatching {
throwableFunction()
1
}
assertEquals(
expected = 1,
actual = value.get() // returns 1, or null if the result is an error because throwableFunction() threw
)
} |
I'm sorry if my English is unclear. What I believe to be the issue is "the possibility of indeterminate behavior." I don't intend to discuss how to implement the example code without bugs. If the following code is removed, it will be beneficial because it will prevent the possibility of implementing it in a way that leads to indeterminate behavior. The proposed code can still be implemented without this code. contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
} |
The
runCatching
function was initially set toInvocationKind.EXACTLY_ONCE
, which could lead to indeterminate behavior. Therefore, it has been changed toInvocationKind.AT_MOST_ONCE
.The problem occurs in the following case:
With
InvocationKind.EXACTLY_ONCE
, it is assumed thatvalue = 1
is executed. However, in practice, this may not happen, resulting in an indeterminate value (0).