Compare commits

...

1 Commits

Author SHA1 Message Date
Dhruv Manilawala
d3db7cb04d Avoid declarations in exception control flow 2024-12-13 18:17:50 +05:30
3 changed files with 30 additions and 18 deletions

View File

@@ -205,7 +205,11 @@ impl<'db> SemanticIndexBuilder<'db> {
}
fn flow_merge(&mut self, state: FlowSnapshot) {
self.current_use_def_map_mut().merge(state);
self.current_use_def_map_mut().merge(state, false);
}
fn flow_merge_no_declarations(&mut self, state: FlowSnapshot) {
self.current_use_def_map_mut().merge(state, true);
}
fn add_symbol(&mut self, name: Name) -> ScopedSymbolId {
@@ -1002,7 +1006,7 @@ where
// Prepare for visiting the `except` block(s)
self.flow_restore(pre_try_block_state);
for state in try_block_snapshots {
self.flow_merge(state);
self.flow_merge_no_declarations(state);
}
let pre_except_state = self.flow_snapshot();

View File

@@ -544,7 +544,7 @@ impl<'db> UseDefMapBuilder<'db> {
/// Merge the given snapshot into the current state, reflecting that we might have taken either
/// path to get here. The new state for each symbol should include definitions from both the
/// prior state and the snapshot.
pub(super) fn merge(&mut self, snapshot: FlowSnapshot) {
pub(super) fn merge(&mut self, snapshot: FlowSnapshot, exclude_declarations: bool) {
// We never remove symbols from `symbol_states` (it's an IndexVec, and the symbol
// IDs must line up), so the current number of known symbols must always be equal to or
// greater than the number of known symbols in a previously-taken snapshot.
@@ -553,7 +553,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.merge(snapshot);
current.merge(snapshot, exclude_declarations);
} else {
// Symbol not present in snapshot, so it's unbound/undeclared from that path.
current.set_may_be_unbound();

View File

@@ -227,24 +227,32 @@ impl SymbolState {
}
/// Merge another [`SymbolState`] into this one.
pub(super) fn merge(&mut self, b: SymbolState) {
pub(super) fn merge(&mut self, b: SymbolState, exclude_declarations: bool) {
let mut a = Self {
bindings: SymbolBindings {
live_bindings: Bindings::default(),
constraints: Constraints::default(),
may_be_unbound: self.bindings.may_be_unbound || b.bindings.may_be_unbound,
},
declarations: SymbolDeclarations {
live_declarations: self.declarations.live_declarations.clone(),
may_be_undeclared: self.declarations.may_be_undeclared
|| b.declarations.may_be_undeclared,
declarations: {
if exclude_declarations {
self.declarations.clone()
} else {
SymbolDeclarations {
live_declarations: self.declarations.live_declarations.clone(),
may_be_undeclared: self.declarations.may_be_undeclared
|| b.declarations.may_be_undeclared,
}
}
},
};
std::mem::swap(&mut a, self);
self.declarations
.live_declarations
.union(&b.declarations.live_declarations);
if !exclude_declarations {
self.declarations
.live_declarations
.union(&b.declarations.live_declarations);
}
let mut a_defs_iter = a.bindings.live_bindings.iter();
let mut b_defs_iter = b.bindings.live_bindings.iter();
@@ -494,7 +502,7 @@ mod tests {
sym0b.record_binding(ScopedDefinitionId::from_u32(0));
sym0b.record_constraint(ScopedConstraintId::from_u32(0));
sym0a.merge(sym0b);
sym0a.merge(sym0b, false);
let mut sym0 = sym0a;
assert_bindings(&sym0, false, &["0<0>"]);
@@ -507,7 +515,7 @@ mod tests {
sym1b.record_binding(ScopedDefinitionId::from_u32(1));
sym1b.record_constraint(ScopedConstraintId::from_u32(2));
sym1a.merge(sym1b);
sym1a.merge(sym1b, false);
let sym1 = sym1a;
assert_bindings(&sym1, false, &["1<>"]);
@@ -518,12 +526,12 @@ mod tests {
let sym2b = SymbolState::undefined();
sym2a.merge(sym2b);
sym2a.merge(sym2b, false);
let sym2 = sym2a;
assert_bindings(&sym2, true, &["2<3>"]);
// merging different definitions keeps them each with their existing constraints
sym0.merge(sym2);
sym0.merge(sym2, false);
let sym = sym0;
assert_bindings(&sym, true, &["0<0>", "2<3>"]);
}
@@ -560,7 +568,7 @@ mod tests {
let mut sym2 = SymbolState::undefined();
sym2.record_declaration(ScopedDefinitionId::from_u32(2));
sym.merge(sym2);
sym.merge(sym2, false);
assert_declarations(&sym, false, &[1, 2]);
}
@@ -572,7 +580,7 @@ mod tests {
let sym2 = SymbolState::undefined();
sym.merge(sym2);
sym.merge(sym2, false);
assert_declarations(&sym, true, &[1]);
}