diff --git a/crates/red_knot_python_semantic/src/semantic_index/builder.rs b/crates/red_knot_python_semantic/src/semantic_index/builder.rs index 55e11063b7..c89c2f05c8 100644 --- a/crates/red_knot_python_semantic/src/semantic_index/builder.rs +++ b/crates/red_knot_python_semantic/src/semantic_index/builder.rs @@ -348,9 +348,9 @@ impl<'db> SemanticIndexBuilder<'db> { .record_visibility_constraint(VisibilityConstraint::VisibleIf(constraint)) } - fn reset_visibility_constraints(&mut self, snapshot: FlowSnapshot) { + fn simplify_visibility_constraints(&mut self, snapshot: FlowSnapshot) { self.current_use_def_map_mut() - .reset_visibility_constraints(snapshot); + .simplify_visibility_constraints(snapshot); } fn record_negated_visibility_constraint( @@ -916,7 +916,7 @@ where self.flow_merge(post_clause_state); } - self.reset_visibility_constraints(pre_if); + self.simplify_visibility_constraints(pre_if); } ast::Stmt::While(ast::StmtWhile { test, @@ -960,7 +960,7 @@ where self.flow_merge(break_state); } - self.reset_visibility_constraints(pre_loop); + self.simplify_visibility_constraints(pre_loop); } ast::Stmt::With(ast::StmtWith { items, @@ -1092,7 +1092,7 @@ where self.flow_merge(post_clause_state); } - self.reset_visibility_constraints(after_subject); + self.simplify_visibility_constraints(after_subject); } ast::Stmt::Try(ast::StmtTry { body, @@ -1354,7 +1354,7 @@ where self.visit_expr(orelse); self.record_negated_visibility_constraint(visibility_constraint); self.flow_merge(post_body); - self.reset_visibility_constraints(pre_if); + self.simplify_visibility_constraints(pre_if); } ast::Expr::ListComp( list_comprehension @ ast::ExprListComp { @@ -1459,7 +1459,7 @@ where self.flow_merge(snapshot); } - self.reset_visibility_constraints(pre_op); + self.simplify_visibility_constraints(pre_op); } _ => { walk_expr(self, expr); diff --git a/crates/red_knot_python_semantic/src/semantic_index/use_def.rs b/crates/red_knot_python_semantic/src/semantic_index/use_def.rs index a22b5e7183..80ffef90dd 100644 --- a/crates/red_knot_python_semantic/src/semantic_index/use_def.rs +++ b/crates/red_knot_python_semantic/src/semantic_index/use_def.rs @@ -547,7 +547,25 @@ impl<'db> UseDefMapBuilder<'db> { new_constraint_id } - pub(super) fn reset_visibility_constraints(&mut self, snapshot: FlowSnapshot) { + /// This method resets the visibility constraints for all symbols to a previous state + /// *if* there have been no new declarations or bindings since then. Consider the + /// following example: + /// ```py + /// x = 0 + /// y = 0 + /// if test_a: + /// y = 1 + /// elif test_b: + /// y = 2 + /// elif test_c: + /// y = 3 + /// + /// # RESET + /// ``` + /// We build a complex visibility constraint for the `y = 0` binding. We build the same + /// constraint for the `x = 0` binding as well, but at the `RESET` point, we can get rid + /// of it, as the `if`-`elif`-`elif` chain doesn't include any new bindings of `x`. + pub(super) fn simplify_visibility_constraints(&mut self, snapshot: FlowSnapshot) { let num_symbols = self.symbol_states.len(); debug_assert!(num_symbols >= snapshot.symbol_states.len()); @@ -556,7 +574,7 @@ impl<'db> UseDefMapBuilder<'db> { let mut snapshot_definitions_iter = snapshot.symbol_states.into_iter(); for current in &mut self.symbol_states { if let Some(snapshot) = snapshot_definitions_iter.next() { - current.reset_visibility_constraints(snapshot); + current.simplify_visibility_constraints(snapshot); } else { // Symbol not present in snapshot, keep visibility constraints } diff --git a/crates/red_knot_python_semantic/src/semantic_index/use_def/symbol_state.rs b/crates/red_knot_python_semantic/src/semantic_index/use_def/symbol_state.rs index 500f8828d8..e2c93f2db7 100644 --- a/crates/red_knot_python_semantic/src/semantic_index/use_def/symbol_state.rs +++ b/crates/red_knot_python_semantic/src/semantic_index/use_def/symbol_state.rs @@ -265,7 +265,7 @@ impl SymbolState { .record_visibility_constraint(visibility_constraints, constraint); } - pub(super) fn reset_visibility_constraints(&mut self, snapshot_state: SymbolState) { + pub(super) fn simplify_visibility_constraints(&mut self, snapshot_state: SymbolState) { if self.bindings.live_bindings == snapshot_state.bindings.live_bindings { self.bindings.visibility_constraints = snapshot_state.bindings.visibility_constraints; }