在 Kotlin 運算式中,例如
fun main() {
throw throw throw RuntimeException("boom")
}
或者
fun main() {
throw throw return
}
語法正確
我理解它背后的想法,但我想知道為什么在寫這樣的廢話時沒有警告(至少在 Itellij 中)。
uj5u.com熱心網友回復:
這在KT-22621 "throw throw Exception()": False negative UNREACHABLE_CODE warning 中被報告為一個小問題。需要注意的是,如果你加上括號,會警告無法訪問的代碼:
throw (throw Exception())
// or
throw (return)
此外,也return throws Exception()發出警告。
不幸的是,它在 4 年后仍然是一個懸而未決的問題。
在閱讀了 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)
}
考慮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, or 中發生的情況進行比較visitCallExpression,但您需要更深入地追蹤。
這不會對控制流分析產生太大影響,因為生成的 CFG 部分throw Exception()是正確的。CFG最終確實缺少一個節點來表示外部throw,這就是builder.throwException添加的內容。該節點將被標記為無法訪問并發出警告,但該節點甚至不存在,因此沒有警告。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/377853.html
