en expresiones de Kotlin como
fun main() { throw throw throw RuntimeException("boom") }o
fun main() { throw throw return }son sintácticamente correctos
Entiendo las ideas detrás de esto, pero me pregunto por qué no hay Warn (al menos en Itellij) al escribir tales tonterías.
Esto se informa como un problema menor en KT-22621 "throw throw Exception()": advertencia de UNREACHABLE_CODE falso negativo . Cabe señalar que se advierte código inalcanzable si pones paréntesis:
throw (throw Exception()) // or throw (return) Además, return throws Exception() también da la advertencia.
Desafortunadamente, sigue siendo un problema abierto después de 4 años.
Después de leer un poco el código fuente de Kotlin, creo que esto no es intencional. Consideremos 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) } Considere throw throw Exception() . Cuando se visita el primer throw , generateInstructions(thrownExpression) genera la parte del CFG que corresponde a throw Exception() . Esto hace que se visite el segundo throw , generando el CFG correcto para throw Exception() .
El problema surge cuando se builder.getValue(thrownExpression) . Esto obtiene un PseudoValue del constructor CFG que representa el valor arrojado. Sin embargo, (sospecho que) esto devuelve nil y builder.throwException no se llama. Esto se debe a que al compilar el CFG para throw Exception() , no se vincula ningún valor. Compare esto con lo que sucede en visitParenthesizedExpression o visitCallExpression , pero necesitaría un seguimiento más profundo.
Esto no afecta demasiado al análisis del flujo de control, ya que la parte del CFG generada para throw Exception() es correcta. Sin embargo, al CFG le falta un nodo para representar el throw externo, que es lo que habría agregado builder.throwException . Este nodo se habría marcado como inalcanzable y se habría emitido una advertencia, pero este nodo ni siquiera existe, por lo que no hay advertencias.