ruff/crates
Carl Meyer 595b1aa4a1
[red-knot] per-definition inference, use-def maps (#12269)
Implements definition-level type inference, with basic control flow
(only if statements and if expressions so far) in Salsa.

There are a couple key ideas here:

1) We can do type inference queries at any of three region
granularities: an entire scope, a single definition, or a single
expression. These are represented by the `InferenceRegion` enum, and the
entry points are the salsa queries `infer_scope_types`,
`infer_definition_types`, and `infer_expression_types`. Generally
per-scope will be used for scopes that we are directly checking and
per-definition will be used anytime we are looking up symbol types from
another module/scope. Per-expression should be uncommon: used only for
the RHS of an unpacking or multi-target assignment (to avoid
re-inferring the RHS once per symbol defined in the assignment) and for
test nodes in type narrowing (e.g. the `test` of an `If` node). All
three queries return a `TypeInference` with a map of types for all
definitions and expressions within their region. If you do e.g.
scope-level inference, when it hits a definition, or an
independently-inferable expression, it should use the relevant query
(which may already be cached) to get all types within the smaller
region. This avoids double-inferring smaller regions, even though larger
regions encompass smaller ones.

2) Instead of building a control-flow graph and lazily traversing it to
find definitions which reach a use of a name (which is O(n^2) in the
worst case), instead semantic indexing builds a use-def map, where every
use of a name knows which definitions can reach that use. We also no
longer track all definitions of a symbol in the symbol itself; instead
the use-def map also records which defs remain visible at the end of the
scope, and considers these the publicly-visible definitions of the
symbol (see below).

Major items left as TODOs in this PR, to be done in follow-up PRs:

1) Free/global references aren't supported yet (only lookup based on
definitions in current scope), which means the override-check example
doesn't currently work. This is the first thing I'll fix as follow-up to
this PR.

2) Control flow outside of if statements and expressions.

3) Type narrowing.

There are also some smaller relevant changes here:

1) Eliminate `Option` in the return type of member lookups; instead
always return `Type::Unbound` for a name we can't find. Also use
`Type::Unbound` for modules we can't resolve (not 100% sure about this
one yet.)

2) Eliminate the use of the terms "public" and "root" to refer to
module-global scope or symbols. Instead consistently use the term
"module-global". It's longer, but it's the clearest, and the most
consistent with typical Python terminology. In particular I don't like
"public" for this use because it has other implications around author
intent (is an underscore-prefixed module-global symbol "public"?). And
"root" is just not commonly used for this in Python.

3) Eliminate the `PublicSymbol` Salsa ingredient. Many non-module-global
symbols can also be seen from other scopes (e.g. by a free var in a
nested scope, or by class attribute access), and thus need to have a
"public type" (that is, the type not as seen from a particular use in
the control flow of the same scope, but the type as seen from some other
scope.) So all symbols need to have a "public type" (here I want to keep
the use of the term "public", unless someone has a better term to
suggest -- since it's "public type of a symbol" and not "public symbol"
the confusion with e.g. initial underscores is less of an issue.) At
least initially, I would like to try not having special handling for
module-global symbols vs other symbols.

4) Switch to using "definitions that reach end of scope" rather than
"all definitions" in determining the public type of a symbol. I'm
convinced that in general this is the right way to go. We may want to
refine this further in future for some free-variable cases, but it can
be changed purely by making changes to the building of the use-def map
(the `public_definitions` index in it), without affecting any other
code. One consequence of combining this with no control-flow support
(just last-definition-wins) is that some inference tests now give more
wrong-looking results; I left TODO comments on these tests to fix them
when control flow is added.

And some potential areas for consideration in the future:

1) Should `symbol_ty` be a Salsa query? This would require making all
symbols a Salsa ingredient, and tracking even more dependencies. But it
would save some repeated reconstruction of unions, for symbols with
multiple public definitions. For now I'm not making it a query, but open
to changing this in future with actual perf evidence that it's better.
2024-07-16 11:02:30 -07:00
..
red_knot [red-knot] per-definition inference, use-def maps (#12269) 2024-07-16 11:02:30 -07:00
red_knot_module_resolver [red-knot] Add `walk_directories` to `System` (#12297) 2024-07-16 06:40:10 +00:00
red_knot_python_semantic [red-knot] per-definition inference, use-def maps (#12269) 2024-07-16 11:02:30 -07:00
ruff Bump version to v0.5.2 (#12316) 2024-07-14 10:43:58 -04:00
ruff_benchmark [red-knot] Rename `FileSystem` to `System` (#12214) 2024-07-09 07:20:51 +00:00
ruff_cache Fix cache key collisions for paths with separators (#12159) 2024-07-03 07:36:46 -05:00
ruff_db [red-knot] per-definition inference, use-def maps (#12269) 2024-07-16 11:02:30 -07:00
ruff_dev Drop deprecated `nursery` rule group (#10172) 2024-06-27 13:44:11 +02:00
ruff_diagnostics Move sub-crates to workspace dependencies (#11407) 2024-05-13 14:37:50 +00:00
ruff_formatter Use `indentation` consistently (#12293) 2024-07-12 14:08:56 +02:00
ruff_index [red-knot] per-definition inference, use-def maps (#12269) 2024-07-16 11:02:30 -07:00
ruff_linter Remove `BindingKind::ComprehensionVar` (#12347) 2024-07-16 11:18:04 -04:00
ruff_macros Drop deprecated `nursery` rule group (#10172) 2024-06-27 13:44:11 +02:00
ruff_notebook Add Jupyter Notebook document change snapshot test (#11944) 2024-06-21 05:29:27 +00:00
ruff_python_ast Update Rust crate compact_str to 0.8.0 (#12333) 2024-07-15 06:03:23 +00:00
ruff_python_ast_integration_tests Rename `PreorderVisitor` to `SourceOrderVisitor` (#11798) 2024-06-07 17:01:58 +00:00
ruff_python_codegen Use `indentation` consistently (#12293) 2024-07-12 14:08:56 +02:00
ruff_python_formatter Insert empty line between suite and alternative branch after def/class (#12294) 2024-07-15 12:59:33 +02:00
ruff_python_index Enable token-based rules on source with syntax errors (#11950) 2024-07-02 08:57:46 +00:00
ruff_python_literal Remove some unused `pub` functions (#11576) 2024-05-28 09:56:51 -04:00
ruff_python_parser Enable token-based rules on source with syntax errors (#11950) 2024-07-02 08:57:46 +00:00
ruff_python_resolver chore(deps): update rust crate insta to v1.38.0 (#10701) 2024-04-01 15:44:30 +00:00
ruff_python_semantic Remove `BindingKind::ComprehensionVar` (#12347) 2024-07-16 11:18:04 -04:00
ruff_python_stdlib Regenerate sys.rs with stdlibs==2024.5.15 (#11437) 2024-05-15 22:17:32 +00:00
ruff_python_trivia Mention that `Cursor` is based on rustc's implementation. (#12109) 2024-06-30 16:53:25 +01:00
ruff_python_trivia_integration_tests Build `CommentRanges` outside the parser (#11792) 2024-06-09 09:55:17 +00:00
ruff_server Build settings index in parallel for the native server (#12299) 2024-07-15 09:57:54 +00:00
ruff_source_file red-knot: `source_text`, `line_index`, and `parsed_module` queries (#11822) 2024-06-13 07:37:02 +00:00
ruff_text_size Upgrade to Rust 1.79 (#11875) 2024-06-17 07:15:10 +01:00
ruff_wasm Show syntax errors on the playground (#12083) 2024-06-28 13:06:15 +05:30
ruff_workspace Use more threads when discovering python files (#12258) 2024-07-10 09:29:17 +02:00