Remove suite body tracking from SemanticModel (#5848)

## Summary

The `SemanticModel` currently stores the "body" of a given `Suite`,
along with the current statement index. This is used to support "next
sibling" queries, but we only use this in exactly one place -- the rule
that simplifies constructs like this to `any` or `all`:

```python
for x in y:
    if x == 0:
        return True
return False
```

Instead of tracking the state, we can just do a (slightly more
expensive) traversal, by finding the node within its parent and
returning the next node in the body.

Note that we'll only have to do this extremely rarely -- namely, for
functions that contain something like:

```python
for x in y:
    if x == 0:
        return True
```
This commit is contained in:
Charlie Marsh 2023-07-18 18:58:31 -04:00 committed by GitHub
parent a93254f026
commit 2d505e2b04
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 340 additions and 250 deletions

View file

@ -108,10 +108,6 @@ pub struct SemanticModel<'a> {
/// by way of the `global x` statement.
rebinding_scopes: HashMap<BindingId, Vec<ScopeId>, BuildNoHashHasher<BindingId>>,
/// Body iteration; used to peek at siblings.
pub body: &'a [Stmt],
pub body_index: usize,
/// Flags for the semantic model.
pub flags: SemanticModelFlags,
@ -137,8 +133,6 @@ impl<'a> SemanticModel<'a> {
shadowed_bindings: IntMap::default(),
delayed_annotations: IntMap::default(),
rebinding_scopes: IntMap::default(),
body: &[],
body_index: 0,
flags: SemanticModelFlags::new(path),
handled_exceptions: Vec::default(),
}
@ -757,11 +751,6 @@ impl<'a> SemanticModel<'a> {
self.exprs.iter().rev().skip(1)
}
/// Return the `Stmt` that immediately follows the current `Stmt`, if any.
pub fn sibling_stmt(&self) -> Option<&'a Stmt> {
self.body.get(self.body_index + 1)
}
/// Returns a reference to the global scope
pub fn global_scope(&self) -> &Scope<'a> {
self.scopes.global()