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 8feb891343..acf0fcae96 100644 --- a/crates/red_knot_python_semantic/src/semantic_index/builder.rs +++ b/crates/red_knot_python_semantic/src/semantic_index/builder.rs @@ -292,54 +292,10 @@ impl<'db> SemanticIndexBuilder<'db> { (constraint_id, constraint) } - fn build_constraint(&mut self, constraint_node: &Expr) -> Constraint<'db> { - let expression = self.add_standalone_expression(constraint_node); - Constraint { - node: ConstraintNode::Expression(expression), - is_positive: true, - } - } - - fn add_constraint(&mut self, constraint: Constraint<'db>) -> ScopedConstraintId { - self.current_use_def_map_mut().add_constraint(constraint) - } - - fn add_negated_constraint(&mut self, constraint: Constraint<'db>) -> ScopedConstraintId { - let negated = Constraint { - node: constraint.node, - is_positive: false, - }; - self.current_use_def_map_mut().add_constraint(negated) - } - - fn record_constraint_id(&mut self, constraint: ScopedConstraintId) { - self.current_use_def_map_mut() - .record_constraint_id(constraint) - } - fn record_constraint(&mut self, constraint: Constraint<'db>) -> ScopedConstraintId { self.current_use_def_map_mut().record_constraint(constraint) } - fn record_negated_constraint(&mut self, constraint: Constraint<'db>) -> ScopedConstraintId { - let constraint_id = self.add_negated_constraint(constraint); - self.record_constraint_id(constraint_id); - constraint_id - } - - fn add_visibility_constraint( - &mut self, - constraint: VisibilityConstraint, - ) -> ScopedVisibilityConstraintId { - self.current_use_def_map_mut() - .add_visibility_constraint(constraint) - } - - fn record_visibility_constraint_id(&mut self, constraint: ScopedVisibilityConstraintId) { - self.current_use_def_map_mut() - .record_visibility_constraint_id(constraint) - } - fn record_visibility_constraint( &mut self, constraint: ScopedConstraintId, @@ -361,6 +317,23 @@ impl<'db> SemanticIndexBuilder<'db> { .record_visibility_constraint(VisibilityConstraint::VisibleIfNot(constraint)) } + fn build_constraint(&mut self, constraint_node: &Expr) -> Constraint<'db> { + let expression = self.add_standalone_expression(constraint_node); + Constraint { + node: ConstraintNode::Expression(expression), + is_positive: true, + } + } + + fn record_negated_constraint(&mut self, constraint: Constraint<'db>) -> ScopedConstraintId { + let negated = Constraint { + node: constraint.node, + is_positive: false, + }; + let constraint_id = self.current_use_def_map_mut().record_constraint(negated); + constraint_id + } + fn push_assignment(&mut self, assignment: CurrentAssignment<'db>) { self.current_assignments.push(assignment); } @@ -1415,34 +1388,36 @@ where let mut snapshots = vec![]; let mut visibility_constraints = vec![]; + let mut last_constraint = None; for (index, value) in values.iter().enumerate() { self.visit_expr(value); - - for id in &visibility_constraints { - self.record_visibility_constraint_id(*id); + if let Some(id) = last_constraint { + visibility_constraints.push(self.record_visibility_constraint(id)); } - - // In the last value we don't need to take a snapshot nor add a constraint + // Snapshot is taken after visiting the expression but before adding the constraint. + snapshots.push(self.flow_snapshot()); if index < values.len() - 1 { + // In the last value we don't need to add a constraint let constraint = self.build_constraint(value); let id = match op { - BoolOp::And => self.add_constraint(constraint), - BoolOp::Or => self.add_negated_constraint(constraint), + BoolOp::And => self.record_constraint(constraint), + BoolOp::Or => self.record_negated_constraint(constraint), }; - let visibility_constraint = - self.add_visibility_constraint(VisibilityConstraint::VisibleIf(id)); - visibility_constraints.push(visibility_constraint); - self.record_negated_visibility_constraint(visibility_constraint); - - // Snapshot is taken after visiting the expression and adding the visibility - // constraint, but before adding the narrowing constraint. - snapshots.push(self.flow_snapshot()); - - self.record_constraint_id(id); + last_constraint = Some(id); } } + let mut snapshots = snapshots.into_iter(); + let first = snapshots.next().expect("at least one value"); + self.flow_restore(first); + + // debug_assert(constraints.len() == snapshots.len()); + + for id in visibility_constraints { + self.record_negated_visibility_constraint(id); + } + for snapshot in snapshots { self.flow_merge(snapshot); } 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 965cf184c3..78045de6b9 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 @@ -496,48 +496,27 @@ impl<'db> UseDefMapBuilder<'db> { symbol_state.record_binding(def_id); } - pub(super) fn add_constraint(&mut self, constraint: Constraint<'db>) -> ScopedConstraintId { - self.all_constraints.push(constraint) - } - - pub(super) fn record_constraint_id(&mut self, constraint: ScopedConstraintId) { - for state in &mut self.symbol_states { - state.record_constraint(constraint); - } - } - pub(super) fn record_constraint(&mut self, constraint: Constraint<'db>) -> ScopedConstraintId { - let constraint_id = self.add_constraint(constraint); - self.record_constraint_id(constraint_id); - constraint_id - } - - pub(super) fn add_visibility_constraint( - &mut self, - constraint: VisibilityConstraint, - ) -> ScopedVisibilityConstraintId { - self.visibility_constraints.add(constraint) - } - - pub(super) fn record_visibility_constraint_id( - &mut self, - constraint: ScopedVisibilityConstraintId, - ) { + let constraint_id = self.all_constraints.push(constraint); for state in &mut self.symbol_states { - state.record_visibility_constraint(&mut self.visibility_constraints, constraint); + state.record_constraint(constraint_id); } - - self.unbound_visibility = self - .visibility_constraints - .add_sequence(self.unbound_visibility, constraint); + constraint_id } pub(super) fn record_visibility_constraint( &mut self, constraint: VisibilityConstraint, ) -> ScopedVisibilityConstraintId { - let new_constraint_id = self.add_visibility_constraint(constraint); - self.record_visibility_constraint_id(new_constraint_id); + let new_constraint_id = self.visibility_constraints.add(constraint); + for state in &mut self.symbol_states { + state.record_visibility_constraint(&mut self.visibility_constraints, new_constraint_id); + } + + self.unbound_visibility = self + .visibility_constraints + .add_sequence(self.unbound_visibility, new_constraint_id); + new_constraint_id }