diff --git a/pyrefly/lib/binding/scope.rs b/pyrefly/lib/binding/scope.rs index ca0d0083f3..004bc68c72 100644 --- a/pyrefly/lib/binding/scope.rs +++ b/pyrefly/lib/binding/scope.rs @@ -3845,13 +3845,14 @@ fn determine_definition_status( n_values: usize, n_branches: usize, n_missing_branches: usize, - n_branches_with_termination_key: usize, missing_branch_termination_keys: Vec>, ) -> DefinitionStatus { match merge_style { MergeStyle::LoopDefinitelyRuns if base_has_value => DefinitionStatus::Defined, MergeStyle::LoopDefinitelyRuns if n_values == n_branches => DefinitionStatus::Defined, - MergeStyle::LoopDefinitelyRuns if n_missing_branches <= n_branches_with_termination_key => { + MergeStyle::LoopDefinitelyRuns + if n_missing_branches <= missing_branch_termination_keys.len() => + { if !missing_branch_termination_keys.is_empty() { DefinitionStatus::DeferredCheck(missing_branch_termination_keys) } else { @@ -3859,7 +3860,7 @@ fn determine_definition_status( } } _ if n_values == n_branches => DefinitionStatus::Defined, - _ if n_missing_branches <= n_branches_with_termination_key => { + _ if n_missing_branches <= missing_branch_termination_keys.len() => { if !missing_branch_termination_keys.is_empty() { DefinitionStatus::DeferredCheck(missing_branch_termination_keys) } else { @@ -3952,7 +3953,6 @@ impl<'a> BindingsBuilder<'a> { phi_key: PhiKey, merge_style: MergeStyle, n_branches: usize, - n_branches_with_termination_key: usize, ) -> FlowInfo { // Only a promised phi can already appear in a branch's flow. let phi_idx = phi_key.promised; @@ -4080,7 +4080,6 @@ impl<'a> BindingsBuilder<'a> { n_values, n_branches, n_missing_branches, - n_branches_with_termination_key, missing_branch_termination_keys, ); @@ -4213,10 +4212,6 @@ impl<'a> BindingsBuilder<'a> { 0 }; - // Count how many branches have a last_stmt_expr (potential type-based termination) - let n_branches_with_termination_key = - flows.iter().filter(|f| f.last_stmt_expr.is_some()).count(); - // Collect all termination keys from flows (for building dense MergeItems) let all_termination_keys: Vec>> = flows.iter().map(|f| f.last_stmt_expr).collect(); @@ -4263,13 +4258,7 @@ impl<'a> BindingsBuilder<'a> { promised: self.promised_idx(&key), key, }; - let flow_info = self.merged_flow_info( - merge_item, - phi_key, - merge_style, - n_branches, - n_branches_with_termination_key, - ); + let flow_info = self.merged_flow_info(merge_item, phi_key, merge_style, n_branches); merged_flow_infos.insert_hashed(name, flow_info); } diff --git a/pyrefly/lib/test/flow_branching.rs b/pyrefly/lib/test/flow_branching.rs index d7fe0b4e66..d17d8a6e5f 100644 --- a/pyrefly/lib/test/flow_branching.rs +++ b/pyrefly/lib/test/flow_branching.rs @@ -2283,7 +2283,6 @@ def f() -> int: // elif condition only executes if the first `if` was False — walrus may not run. testcase!( - bug = "In order to fix false positives, we handled narrows differently in if/elif and introduced a false negative here", test_walrus_in_elif, r#" def condition() -> bool: ... @@ -2292,7 +2291,7 @@ def f() -> bool: pass elif (x := condition()): pass - return x # False negative: x winds up getting applied as if it were in the base flow due to the negative narrow + return x # E: `x` may be uninitialized "#, ); @@ -2380,7 +2379,6 @@ def f() -> None: // the walrus may not execute, so x should be possibly-uninitialized. testcase!( - bug = "Should report x as possibly uninitialized since the if branch does not terminate", test_walrus_in_elif_preceding_if_no_terminate, r#" def foo() -> bool: @@ -2394,7 +2392,7 @@ def f() -> None: pass elif (x := bar()) > 1: pass - print(x) # should be an error: x may be uninitialized + print(x) # E: `x` may be uninitialized "#, ); diff --git a/pyrefly/lib/test/flow_looping.rs b/pyrefly/lib/test/flow_looping.rs index 3ffb14c217..e5ed74743d 100644 --- a/pyrefly/lib/test/flow_looping.rs +++ b/pyrefly/lib/test/flow_looping.rs @@ -8,6 +8,19 @@ use crate::test::util::TestEnv; use crate::testcase; +testcase!( + test_for_trailing_expression_does_not_initialize_local, + r#" +import time + +def f(xs: list[int]) -> int: + for x in xs: + y = x + time.sleep(1) + return y # E: `y` may be uninitialized +"#, +); + testcase!( test_loop_with_generic_pin, r#" diff --git a/pyrefly/lib/test/scope.rs b/pyrefly/lib/test/scope.rs index a92759de9a..7ec88002d1 100644 --- a/pyrefly/lib/test/scope.rs +++ b/pyrefly/lib/test/scope.rs @@ -1071,7 +1071,7 @@ def try_except_twice(): except Exception: e3 # E: `e3` is uninitialized - e3 # E: `e3` may be uninitialized + e3 # E: `e3` is uninitialized def try_except_multiple_finally(): try: