Raghav
06/10/2026, 10:22 AMusedAsExpression flag in the FIR API is internal and not to be relied on, but I was curious about the rationale for this flag being false when, say an expression is used as an implicit return from a lambda.
val a: (Int) -> Boolean = { i ->
if (i > 3) { true } // the if isn't used as an expression?
else { false }
}
Digging into the builder logic, I see that if the current node is the last child of its parent, the usedAsExpression flag of the parent is checked... it seems like oneline functions like fun a() = ... evaluate to true, but the parent check returns false for function literal parents...
Why does it work that way? are there situations where it makes more sense to consider expressions that are implicitly returned to not be used as expressions? I'd love to hear from anybody who's worked on FIR, thanks in advance!dmitriy.novozhilov
06/15/2026, 7:18 AM// when is used as expression
val a: (Int) -> Boolean = { i ->
when {
i > 3 -> true
}
}
// lambda coerced to Unit
val b: (Int) -> Unit = { i ->
when {
i > 3 -> true
}
}
So here we have two options:
• set usedAsExpression to true here, which will result in NO_ELSE_IN_WHEN for a and b
• set it to false, which will lead to no NO_ELSE_IN_WHEN diagnostics (as both whens wouldn't be required to be exhaustive) but to RETURN_TYPE_MISMATCH for a (as type of when would be inferred to Unit).
Considering that code in b is correct and nothing should be reported, the second option was chosen.Raghav
06/16/2026, 7:10 AMdmitriy.novozhilov
06/16/2026, 7:11 AMusedAsExpression without resolution of the code.Raghav
06/16/2026, 7:17 AM