Skip to content

Commit

Permalink
Fix boolean expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
sharkdp committed Dec 18, 2024
1 parent e902f98 commit 79a1b6b
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 42 deletions.
95 changes: 60 additions & 35 deletions crates/red_knot_python_semantic/src/semantic_index/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,54 @@ 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,
Expand All @@ -317,23 +361,6 @@ 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);
}
Expand Down Expand Up @@ -1388,34 +1415,32 @@ 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);
if let Some(id) = last_constraint {
visibility_constraints.push(self.record_visibility_constraint(id));

for id in &visibility_constraints {
self.record_visibility_constraint_id(*id);
}
// Snapshot is taken after visiting the expression but before adding the constraint.
snapshots.push(self.flow_snapshot());

// In the last value we don't need to take a snapshot nor add a constraint
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.record_constraint(constraint),
BoolOp::Or => self.record_negated_constraint(constraint),
BoolOp::And => self.add_constraint(constraint),
BoolOp::Or => self.add_negated_constraint(constraint),
};
last_constraint = Some(id);
}
}

let mut snapshots = snapshots.into_iter();
let first = snapshots.next().expect("at least one value");
self.flow_restore(first);
let visibility_constraint =
self.add_visibility_constraint(VisibilityConstraint::VisibleIf(id));
visibility_constraints.push(visibility_constraint);
self.record_negated_visibility_constraint(visibility_constraint);

// debug_assert(constraints.len() == snapshots.len());
// Snapshot is taken after visiting the expression and adding the visibility
// constraint, but before adding the narrowing constraint.
snapshots.push(self.flow_snapshot());

for id in visibility_constraints {
self.record_negated_visibility_constraint(id);
self.record_constraint_id(id);
}
}

for snapshot in snapshots {
Expand Down
35 changes: 28 additions & 7 deletions crates/red_knot_python_semantic/src/semantic_index/use_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,27 +496,48 @@ impl<'db> UseDefMapBuilder<'db> {
symbol_state.record_binding(def_id);
}

pub(super) fn record_constraint(&mut self, constraint: Constraint<'db>) -> ScopedConstraintId {
let constraint_id = self.all_constraints.push(constraint);
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_id);
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 record_visibility_constraint(
pub(super) fn add_visibility_constraint(
&mut self,
constraint: VisibilityConstraint,
) -> ScopedVisibilityConstraintId {
let new_constraint_id = self.visibility_constraints.add(constraint);
self.visibility_constraints.add(constraint)
}

pub(super) fn record_visibility_constraint_id(
&mut self,
constraint: ScopedVisibilityConstraintId,
) {
for state in &mut self.symbol_states {
state.record_visibility_constraint(&mut self.visibility_constraints, new_constraint_id);
state.record_visibility_constraint(&mut self.visibility_constraints, constraint);
}

self.unbound_visibility = self
.visibility_constraints
.add_sequence(self.unbound_visibility, new_constraint_id);
.add_sequence(self.unbound_visibility, constraint);
}

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);
new_constraint_id
}

Expand Down

0 comments on commit 79a1b6b

Please sign in to comment.