From 16beb697ffae294ec742f632c9947c30e7584855 Mon Sep 17 00:00:00 2001 From: Turiiya <34311583+ttytm@users.noreply.github.com> Date: Wed, 17 Apr 2024 09:40:20 +0200 Subject: [PATCH] checker: detect and error on unreachable code in loops, after `continue` and `break` statements (#21294) --- vlib/v/checker/checker.v | 5 +++- vlib/v/checker/tests/unreachable_code.out | 33 ++++++++++++++++++----- vlib/v/checker/tests/unreachable_code.vv | 30 +++++++++++++++++++-- 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index e93a6c9b1be2bf..66f012534b81a5 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2600,7 +2600,10 @@ fn (mut c Checker) stmts_ending_with_expression(mut stmts []ast.Stmt) { } } c.stmt(mut stmt) - if stmt is ast.GotoLabel { + if !c.inside_anon_fn && c.in_for_count > 0 && stmt is ast.BranchStmt + && stmt.kind in [.key_continue, .key_break] { + c.scope_returns = true + } else if stmt is ast.GotoLabel { unreachable = token.Pos{ line_nr: -1 } diff --git a/vlib/v/checker/tests/unreachable_code.out b/vlib/v/checker/tests/unreachable_code.out index ae0dc929366f30..3c00f08cc57673 100644 --- a/vlib/v/checker/tests/unreachable_code.out +++ b/vlib/v/checker/tests/unreachable_code.out @@ -1,7 +1,28 @@ -vlib/v/checker/tests/unreachable_code.vv:3:4: error: unreachable code - 1 | fn foo() int { - 2 | return if 1 == 1 { 1 } else { 2 } - 3 | a := 1 +vlib/v/checker/tests/unreachable_code.vv:15:3: error: unreachable code + 13 | continue + 14 | // ... + 15 | eprintln('continue') + | ~~~~~~~~~~~~~~~~~~~~ + 16 | } + 17 | for _ in 0 .. 3 { +vlib/v/checker/tests/unreachable_code.vv:21:4: error: unreachable code + 19 | break + 20 | // ... + 21 | eprintln('done') + | ~~~~~~~~~~~~~~~~ + 22 | } + 23 | break +vlib/v/checker/tests/unreachable_code.vv:25:3: error: unreachable code + 23 | break + 24 | // ... + 25 | return 3 + | ~~~~~~~~ + 26 | } + 27 | return if 1 == 1 { 1 } else { 2 } +vlib/v/checker/tests/unreachable_code.vv:28:4: error: unreachable code + 26 | } + 27 | return if 1 == 1 { 1 } else { 2 } + 28 | a := 1 | ~~ - 4 | println(a) - 5 | } + 29 | println(a) + 30 | } diff --git a/vlib/v/checker/tests/unreachable_code.vv b/vlib/v/checker/tests/unreachable_code.vv index 7da480f8aa3e7a..417ac60ebae196 100644 --- a/vlib/v/checker/tests/unreachable_code.vv +++ b/vlib/v/checker/tests/unreachable_code.vv @@ -1,8 +1,34 @@ -fn foo() int { +fn foo(condition bool) int { + for _ in 0 .. 1 { + if condition { + continue // scope should not cause errors. + } + if !condition { + break + } + eprintln('done') + break + } + for _ in 0 .. 2 { + continue + // ... + eprintln('continue') + } + for _ in 0 .. 3 { + if condition { + break + // ... + eprintln('done') + } + break + // ... + return 3 + } return if 1 == 1 { 1 } else { 2 } a := 1 println(a) } + fn main() { - foo() + foo(true) }