ruff/crates/ruff_python_ast/src
Charlie Marsh 76148ddb76
Store call paths rather than stringified names (#6102)
## Summary

Historically, we've stored "qualified names" on our
`BindingKind::Import`, `BindingKind::SubmoduleImport`, and
`BindingKind::ImportFrom` structs. In Ruff, a "qualified name" is a
dot-separated path to a symbol. For example, given `import foo.bar`, the
"qualified name" would be `"foo.bar"`; and given `from foo.bar import
baz`, the "qualified name" would be `foo.bar.baz`.

This PR modifies the `BindingKind` structs to instead store _call paths_
rather than qualified names. So in the examples above, we'd store
`["foo", "bar"]` and `["foo", "bar", "baz"]`. It turns out that this
more efficient given our data access patterns. Namely, we frequently
need to convert the qualified name to a call path (whenever we call
`resolve_call_path`), and it turns out that we do this operation enough
that those conversations show up on benchmarks.

There are a few other advantages to using call paths, rather than
qualified names:

1. The size of `BindingKind` is reduced from 32 to 24 bytes, since we no
longer need to store a `String` (only a boxed slice).
2. All three import types are more consistent, since they now all store
a boxed slice, rather than some storing an `&str` and some storing a
`String` (for `BindingKind::ImportFrom`, we needed to allocate a
`String` to create the qualified name, but the call path is a slice of
static elements that don't require that allocation).
3. A lot of code gets simpler, in part because we now do call path
resolution "earlier". Most notably, for relative imports (`from .foo
import bar`), we store the _resolved_ call path rather than the relative
call path, so the semantic model doesn't have to deal with that
resolution. (See that `resolve_call_path` is simpler, fewer branches,
etc.)

In my testing, this change improves the all-rules benchmark by another
4-5% on top of the improvements mentioned in #6047.
2023-08-05 15:21:50 +00:00
..
visitor Use `range: _` in lieu of `range: _range` (#6296) 2023-08-02 22:11:13 -04:00
all.rs Introduce an `Arguments` AST node for function calls and class definitions (#6259) 2023-08-02 10:01:13 -04:00
call_path.rs Store call paths rather than stringified names (#6102) 2023-08-05 15:21:50 +00:00
cast.rs Pull in RustPython parser (#6099) 2023-07-27 09:29:11 +00:00
comparable.rs Use `range: _` in lieu of `range: _range` (#6296) 2023-08-02 22:11:13 -04:00
docstrings.rs Move Python whitespace utilities into new `ruff_python_whitespace` crate (#4993) 2023-06-10 00:59:57 +00:00
function.rs Add formatting of type parameters in class and function definitions (#6161) 2023-08-02 20:29:28 +00:00
hashable.rs Pull in RustPython parser (#6099) 2023-07-27 09:29:11 +00:00
helpers.rs Store call paths rather than stringified names (#6102) 2023-08-05 15:21:50 +00:00
identifier.rs Rename `Parameter#arg` and `ParameterWithDefault#def` fields (#6255) 2023-08-01 14:28:34 -04:00
imports.rs Include alias when formatting import-from structs (#5786) 2023-07-15 15:53:21 -04:00
lib.rs Formatter: Add SourceType to context to enable special formatting for stub files (#6331) 2023-08-04 11:52:26 +00:00
node.rs Add formatting of type parameters in class and function definitions (#6161) 2023-08-02 20:29:28 +00:00
nodes.rs Return a slice in `StmtClassDef#bases` (#6311) 2023-08-03 16:21:55 +00:00
relocate.rs Introduce an `Arguments` AST node for function calls and class definitions (#6259) 2023-08-02 10:01:13 -04:00
statement_visitor.rs Use `range: _` in lieu of `range: _range` (#6296) 2023-08-02 22:11:13 -04:00
stmt_if.rs Pull in RustPython parser (#6099) 2023-07-27 09:29:11 +00:00
str.rs Basic string formatting 2023-06-23 09:46:05 +02:00
traversal.rs Pull in RustPython parser (#6099) 2023-07-27 09:29:11 +00:00
types.rs Pull in RustPython parser (#6099) 2023-07-27 09:29:11 +00:00
visitor.rs Use `range: _` in lieu of `range: _range` (#6296) 2023-08-02 22:11:13 -04:00
whitespace.rs Ignore end-of-line file exemption comments (#6160) 2023-07-29 00:40:32 +00:00