在 Kotlin 表达式中,例如
fun main() {
throw throw throw RuntimeException("boom")
}
Run Code Online (Sandbox Code Playgroud)
或者
fun main() {
throw throw return
}
Run Code Online (Sandbox Code Playgroud)
语法正确
我理解其背后的想法,但我想知道为什么在写这样的废话时没有警告(至少在 Itellij 中)。
这在 KT-22621“throw throw Exception()”中被报告为一个小问题:漏报 UNREACHABLE_CODE 警告。应该注意的是,如果放入括号,则会警告无法访问的代码:
throw (throw Exception())
// or
throw (return)
Run Code Online (Sandbox Code Playgroud)
另外,return throws Exception()也给出警告。
不幸的是,四年后这仍然是一个悬而未决的问题。
读了一下 Kotlin 的源代码后,我认为这是无意的。让我们考虑 ControlFlowProcessor.kt visitThrowExpression:
override fun visitThrowExpression(expression: KtThrowExpression) {
mark(expression)
generateJumpsToCatchAndFinally()
val thrownExpression = expression.thrownExpression ?: return
generateInstructions(thrownExpression)
val thrownValue = builder.getBoundValue(thrownExpression) ?: return
builder.throwException(expression, thrownValue)
}
Run Code Online (Sandbox Code Playgroud)
考虑throw throw Exception()。当第一个throw被访问时,generateInstructions(thrownExpression)生成 CFG 中对应于 的部分throw Exception()。throw这会导致访问第二个,从而为 生成正确的 CFG throw Exception()。
builder.getValue(thrownExpression)当接到电话时,问题就来了。这会PseudoValue从 CFG 构建器获取表示抛出值的值。但是,(我怀疑)这会返回 nil 并且builder.throwException不会被调用。这是因为在构建 的 CFG 时throw Exception(),没有绑定任何值。将此与visitParenthesizedExpression、 或中发生的情况进行比较visitCallExpression,但您需要更深入地追踪。
这不会对控制流分析产生太大影响,因为生成的 CFG 部分throw Exception()是正确的。CFG最终确实缺少一个代表外部的节点throw,而这正是本builder.throwException应添加的节点。该节点将被标记为无法访问并发出警告,但该节点甚至不存在,因此没有警告。
| 归档时间: |
|
| 查看次数: |
566 次 |
| 最近记录: |