-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add branch detection to the semantic model (#6694)
## Summary We have a few rules that rely on detecting whether two statements are in different branches -- for example, different arms of an `if`-`else`. Historically, the way this was implemented is that, given two statement IDs, we'd find the common parent (by traversing upwards via our `Statements` abstraction); then identify branches "manually" by matching the parents against `try`, `if`, and `match`, and returning iterators over the arms; then check if there's an arm for which one of the statements is a child, and the other is not. This has a few drawbacks: 1. First, the code is generally a bit hard to follow (Konsti mentioned this too when working on the `ElifElseClause` refactor). 2. Second, this is the only place in the codebase where we need to go from `&Stmt` to `StatementID` -- _everywhere_ else, we only need to go in the _other_ direction. Supporting these lookups means we need to maintain a mapping from `&Stmt` to `StatementID` that includes every `&Stmt` in the program. (We _also_ end up maintaining a `depth` level for every statement.) I'd like to get rid of these requirements to improve efficiency, reduce complexity, and enable us to treat AST modes more generically in the future. (When I looked at adding the `&Expr` to our existing statement-tracking infrastructure, maintaining a hash map with all the statements noticeably hurt performance.) The solution implemented here instead makes branches a first-class concept in the semantic model. Like with `Statements`, we now have a `Branches` abstraction, where each branch points to its optional parent. When we store statements, we store the `BranchID` alongside each statement. When we need to detect whether two statements are in the same branch, we just realize each statement's branch path and compare the two. (Assuming that the two statements are in the same scope, then they're on the same branch IFF one branch path is a subset of the other, starting from the top.) We then add some calls to the visitor to push and pop branches in the appropriate places, for `if`, `try`, and `match` statements. Note that a branch is not 1:1 with a statement; instead, each branch is closer to a suite, but not _every_ suite is a branch. For example, each arm in an `if`-`elif`-`else` is a branch, but the `else` in a `for` loop is not considered a branch. In addition to being much simpler, this should also be more efficient, since we've shed the entire `&Stmt` hash map, plus the `depth` that we track on `StatementWithParent` in favor of a single `Option<BranchID>` on `StatementWithParent` plus a single vector for all branches. The lookups should be faster too, since instead of doing a bunch of jumps around with the hash map + repeated recursive calls to find the common parents, we instead just do a few simple lookups in the `Branches` vector to realize and compare the branch paths. ## Test Plan `cargo test` -- we have a lot of coverage for this, which we inherited from PyFlakes
- Loading branch information
1 parent
648333b
commit 17af12e
Showing
24 changed files
with
283 additions
and
298 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.