Tried again K2 and I'm getting the following warni...
# k2-adopters
e
Tried again K2 and I'm getting the following warnings. What do they mean?
d
They indicate that some of your functions with contracts does no actually satisfy this contract
E.g. first and last diagnostics may be reported in such case
Copy code
@OptIn(ExperimentalContracts::class)
fun test(block: () -> Unit) {
    contract { 
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    invokeLater(block)
}

fun invokeLater(block: () -> Unit) {
    // send `block` to thread pool
}
BTW please report an issue about incorrect warning message for the second case
e
Thanks! Indeed the functions with the contracts were not inline, so good catch by K2
d
Note that it's not about
inline
but how you use passed lambda This function is entirely correct
Copy code
@OptIn(ExperimentalContracts::class)
fun notInlineRun(block: () -> Unit) {
    contract { 
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
}
block
is called inside function
test
, caleed exactly once and not saved in any state which potentially may invoke this lambda later
Also K2 assumes that every lambda passed to
inline
function (without
noinline
or
crossinline
modifier) automatically gets contract
callsInPlace(block, InvocationKind.UNKNOWN)
gratitude thank you 1
e
What about
Copy code
public suspend fun <R> ZSocket.use(block: suspend (ZSocket) -> R): R {
  contract {
    callsInPlace(block, InvocationKind.EXACTLY_ONCE)
  }

  var throwable: Throwable? = null
  return try {
    block(this) // Called here
  } catch (t: Throwable) {
    throwable = t
    throw t
  } finally {
    ...
  }
}
This is where it was marking the warning
d
Generally speaking contract here is correct But performing control flow analysis over
try/catch/finally
expression is pain the ass quite hard, so there is a naive assumption which compiler makes, that exception can happen in any place of
try
block, including its very beginning, before call to
block(this)
(well, technically
OutOfMemoryError
actually can be thrown from anywhere). So compiler think that there is a way when function without invocation of
block
Could you please report a ticket about this case to kotl.in/issue? For me it looks like something which can be fixed Contracts verification was added to K2 as a prototype and wasn't properly tested, so such reports will be quite valuable
For your code you can just add
@Suppress("WRONG_INVOCATION_KIND")
if warning annoys you
e
Makes sense. I think in this specific case I could just get rid of the contracts (or add the suppression as you mentioned), but I'll report the issue tonight, no problem.
thank you color 1
k
The warning message should already be fixed.
e
Thanks @kirillrakhman, 1.9.20-dev or 1.9.30-dev?
k
1.9.30-dev
✔️ 2