Commit graph

859 commits

Author SHA1 Message Date
Andrew Gallant
7d958a9ee5 red_knot_python_semantic: remove the "old" secondary message type
This finally completes the deletion of all old diagnostic types.

We do this by migrating the second (and last) use of secondary
diagnostic messages: to highlight the return type of a function
definition when its return value is inconsistent with the type.

Like the last diagnostic, we do actually change the message here a bit.
We don't need a sub-diagnostic here, and we can instead just add a
secondary annotation to highlight the return type.
2025-04-10 13:21:00 -04:00
Andrew Gallant
7e2eb591bc red_knot_python_semantic: replace one use of "old" secondary diagnostic messages
This is the first use of the new `lint()` reporter.

I somewhat skipped a step here and also modified the actual diagnostic
message itself. The snapshots should tell the story.

We couldn't do this before because we had no way of differentiating
between "message for the diagnostic as a whole" and "message for a
specific code annotation." Now we can, so we can write more precise
messages based on the assumption that users are also seeing the code
snippet.

The downside here is that the actual message text can become quite vague
in the absence of the code snippet. This occurs, for example, with
concise diagnostic formatting. It's unclear if we should do anything
about it. I don't really see a way to make it better that doesn't
involve creating diagnostics with messages for each mode, which I think
would be a major PITA.

The upside is that this code gets a bit simpler, and we very
specifically avoid doing extra work if this specific lint is disabled.
2025-04-10 13:21:00 -04:00
Andrew Gallant
ba408f4231 red_knot_python_semantic: update revealed type snapshots
This required a bit of surgery in the diagnostic matching and more
faffing about using a "concise" message from a diagnostic instead of
only printing the "primary" message.
2025-04-10 13:21:00 -04:00
Andrew Gallant
28b64064f5 ruff_db: tweak how the revealed type diagnostic is rendered
In the new diagnostic data model, we really should have a main
diagnostic message *and* a primary span (with an optional message
attached to it) for every diagnostic.

In this commit, I try to make this true for the "revealed type"
diagnostic. Instead of the annotation saying both "revealed type is"
and also the revealed type itself, the annotation is now just the
revealed type and the main diagnostic message is "Revealed type."

I expect this may be controversial. I'm open to doing something
different. I tried to avoid redundancy, but maybe this is a special case
where we want the redundancy. I'm honestly not sure. I do *like* how it
looks with this commit, but I'm not working with Red Knot's type
checking daily, so my opinion doesn't count for much.

This did also require some tweaking to concise diagnostic formatting in
order to preserve the essential information.

This commit doesn't update every relevant snapshot. Just a few. I split
the rest out into the next commit.
2025-04-10 13:21:00 -04:00
Andrew Gallant
e7e86b8584 red_knot_python_semantic: remove InferContext::report_diagnostic
... and replace it with use of `report()`.

Interestingly, this is the only instance of `report_diagnostic` used
directly, and thus anticipated to be the only instance of using
`report()`. If this ends up being a true single use method, we could
make it less generic and tailored specifically to "reveal type."

Two other things to note:

I left the "primary message" as empty. This avoids changing snapshots.
I address this in a subsequent commit.

The creation of a diagnostic here is a bit verbose/annoying. Certainly
more so than it was. This is somewhat expected since our diagnostic
model is more expressive and because we don't have a proc macro. I
avoided creating helpers for this case since there's only one use of
`report()`. But I expect to create helpers for the `lint()` case.
2025-04-10 13:21:00 -04:00
Andrew Gallant
f84bc07d56 red_knot_python_semantic: add "reporter" API
This is a surgical change that adds new `report()` and `lint()`
APIs to `InferContext`. These are intended to replace the existing
`report_*` APIs.

The comments should explain what these reporters are meant to do. For
the most part, this is "just" shuffling some code around. The actual
logic for determining whether a lint *should* be reported or not remains
unchanged and we don't make any changes to how a `Diagnostic` is
actually constructed (yet).

I initially tried to just use `LintReporter` and `DiagnosticReporter`
without the builder types, since I perceive the builder types to be an
annoying additional layer. But I found it also exceedingly annoying to
have to construct and provide the diagnostic message before you even
know if you are going to build the diagnostic. I also felt like this
could result in potentially unnecessary and costly querying in some
cases, although this is somewhat hand wavy. So I overall felt like the
builder route was the way to go. If the builders end up being super
annoying, we can probably add convenience APIs for common patterns to
paper over them.
2025-04-10 13:21:00 -04:00
David Peter
5b6e94981d
[red-knot] Silence unresolved-attribute in unreachable code (#17305)
## Summary

Basically just repeat the same thing that we did for
`unresolved-reference`, but now for attribute expressions.

We now also handle the case where the unresolved attribute (or the
unresolved reference) diagnostic originates from a stringified type
annotation.

And I made the evaluation of reachability constraints lazy (will only be
evaluated right before we are about to emit a diagnostic).

## Test Plan

New Markdown tests for stringified annotations.
2025-04-10 17:15:47 +02:00
Carl Meyer
ec74f2d522
Revert "[red-knot] Type narrowing for assertions (#17149)" (#17335)
I merged #17149 without checking the ecosystem results, and it still
caused a cycle panic in pybind11. Reverting for now until I fix that, so
we don't lose the ecosystem signal on other PRs.
2025-04-10 11:06:25 -04:00
Matthew Mckee
907b6ed7b5
[red-knot] Type narrowing for assertions (#17149)
## Summary

Fixes #17147 

## Test Plan

Add new narrow/assert.md test file

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-10 10:15:52 -04:00
Carl Meyer
fd9882a1f4
[red-knot] avoid unnecessary evaluation of visibility constraint on definitely-unbound symbol (#17326)
This causes spurious query cycles.

This PR also includes an update to Salsa, which gives us db events on
cycle iteration, so we can write tests asserting the absence of a cycle.
2025-04-10 13:59:38 +00:00
David Peter
4d50ee6f52
[red-knot] Track reachability of scopes (#17332)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
## Summary

Track the reachability of nested scopes within their parent scopes. We
use this as an additional requirement for emitting
`unresolved-reference` diagnostics (and in the future,
`unresolved-attribute` and `unresolved-import`). This means that we only
emit `unresolved-reference` for a given use of a symbol if the use
itself is reachable (within its own scope), *and if the scope itself is
reachable*. For example, no diagnostic should be emitted for the use of
`x` here:

```py
if False:
    x = 1

    def f():
        print(x)  # this use of `x` is reachable inside the `f` scope,
                  # but the whole `f` scope is not reachable.
```

There are probably more fine-grained ways of solving this problem, but
they require a more sophisticated understanding of nested scopes (see
#15777, in particular
https://github.com/astral-sh/ruff/issues/15777#issuecomment-2788950267).
But it doesn't seem completely unreasonable to silence *this specific
kind of error* in unreachable scopes.

## Test Plan

Observed changes in reachability tests and ecosystem.
2025-04-10 11:56:40 +00:00
Micha Reiser
9f6913c488
[red-knot] Update salsa (#17320)
Some checks are pending
CI / cargo build (msrv) (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
## Summary

Update Salsa to pull in https://github.com/salsa-rs/salsa/pull/788 which
fixes the, by now, famous *access to field whilst the value is being
initialized*.

This PR also re-enables all tests that previously triggered the panic.

## Test Plan

`cargo test`
2025-04-09 16:22:02 -04:00
David Peter
5fef4d4572
Use python.typing.org for typing documentation links (#17323)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
## Summary

There is a new official URL for the typing documentation:
https://typing.python.org/

Change all https://typing.readthedocs.io/ links to use the new sub
domain, which is slightly shorter and looks more official.

## Test Plan

Tested to see if each and every new URL is accessible. I noticed that
some links go to https://typing.python.org/en/latest/source/stubs.html
which seems to be outdated, but that is a separate issue. The same page
shows up for the old URL.
2025-04-09 20:38:20 +02:00
Alex Waygood
781b653511
[red-knot] Fix false positives on types.UnionType instances in type expressions (#17297) 2025-04-09 18:33:16 +01:00
Alex Waygood
73399029b2
[red-knot] Optimise visibility constraints for *-import definitions (#17317) 2025-04-09 16:53:26 +00:00
Douglas Creager
ff376fc262
[red-knot] Allow explicit specialization of generic classes (#17023)
This PR lets you explicitly specialize a generic class using a subscript
expression. It introduces three new Rust types for representing classes:

- `NonGenericClass`
- `GenericClass` (not specialized)
- `GenericAlias` (specialized)

and two enum wrappers:

- `ClassType` (a non-generic class or generic alias, represents a class
_type_ at runtime)
- `ClassLiteralType` (a non-generic class or generic class, represents a
class body in the AST)

We also add internal support for specializing callables, in particular
function literals. (That is, the internal `Type` representation now
attaches an optional specialization to a function literal.) This is used
in this PR for the methods of a generic class, but should also give us
most of what we need for specializing generic _functions_ (which this PR
does not yet tackle).

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-09 11:18:46 -04:00
Alex Waygood
6ec4c6a97e
[red-knot] Improve handling of visibility constraints in external modules when resolving * imports (#17286) 2025-04-09 14:36:52 +00:00
Alex Waygood
f1ba596f22
[red-knot] Add more tests for * imports (#17315) 2025-04-09 15:10:30 +01:00
Micha Reiser
8249a72412
[red-knot] Default python-platform to current platform (#17183)
Some checks are pending
CI / cargo clippy (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
## Summary

As discussed in https://github.com/astral-sh/ruff/issues/16983 and
"mitigate" said issue for the alpha.

This PR changes the default for `PythonPlatform` to be the current
platform rather than `all`.

I'm not sure if we should be as sophisticated as supporting `ios` and
`android` as defaults but it was easy...

## Test Plan

Updated Markdown tests.

---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-04-09 12:05:18 +02:00
David Peter
00e00b9ad6
[red-knot] Add new 'unreachable code' test case (#17306)
## Summary

This is a new test case that I don't know how to handle yet. It leads to
many false positives in `rich/tests/test_win32_console.py`, which does
something like:

```py
if sys.platform == "win32":
    from windows_only_module import some_symbol

    some_other_symbol = 1

    def some_test_case():
        use(some_symbol)  # Red Knot: unresolved-reference
        use(some_other_symbol)  # Red Knot: unresolved-reference
```

Also adds a test for using unreachable symbols in type annotations or as
class bases.
2025-04-09 11:45:42 +02:00
David Peter
2cee86d807
[red-knot] Add custom __setattr__ support (#16748)
## Summary

Add support for classes with a custom `__setattr__` method.

## Test Plan

New Markdown tests, ecosystem checks.
2025-04-09 08:04:11 +02:00
Mike Perlov
fab7d820bd
[red-knot] Add __init__ arguments check when doing try_call on a class literal (#16512)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / mkdocs (push) Waiting to run
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
## Summary

* Addresses #16511 for simple cases where only `__init__` method is
bound on class or doesn't exist at all.
* fixes a bug with argument counting in bound method diagnostics

Caveats:
* No handling of `__new__` or modified `__call__` on metaclass.
* This leads to a couple of false positive errors in tests

## Test Plan

- A couple new cases in mdtests
- cargo nextest run -p red_knot_python_semantic --no-fail-fast

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
2025-04-08 17:26:20 -04:00
David Peter
b662c3ff7e
[red-knot] Add support for assert_never (#17287)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
## Summary

We already have partial "support" for `assert_never`, because it is
annotated as
```pyi
def assert_never(arg: Never, /) -> Never: ...
```
in typeshed. So we already emit a `invalid-argument-type` diagnostic if
the argument type to `assert_never` is not assignable to `Never`.

That is not enough, however. Gradual types like `Any`, `Unknown`,
`@Todo(…)` or `Any & int` can be assignable to `Never`. Which means that
we didn't issue any diagnostic in those cases.

Also, it seems like `assert_never` deserves a dedicated diagnostic
message, not just a generic "invalid argument type" error.

## Test Plan

New Markdown tests.
2025-04-08 09:31:49 +02:00
David Peter
60f2e67454
[red-knot] Reachability analysis (#17199)
## Summary

This implements a new approach to silencing `unresolved-reference`
diagnostics by keeping track of the reachability of each use of a
symbol. The changes merged in
https://github.com/astral-sh/ruff/pull/17169 are still needed for the
"Use of variable in nested function" test case, but that could also be
solved in another way eventually (see
https://github.com/astral-sh/ruff/issues/15777). We can use the same
technique to silence `unresolved-import` and `unresolved-attribute`
false-positives, but I think this could be merged in isolation.

## Test Plan

New Markdown tests, ecosystem tests
2025-04-08 08:37:20 +02:00
David Peter
3657f798c9
[red-knot] Add --python-platform CLI option (#17284)
## Summary

Add a new `--python-platform` command-line option, in analogy to
`--python-version`.

## Test Plan

Added new integration test.
2025-04-07 21:04:44 +02:00
Matthew Mckee
4a4a376f02
[red-knot] Allow ellipsis default params in stub functions (#17243)
Some checks are pending
CI / cargo clippy (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
## Summary

Fixes #17234

## Test Plan

Add tests to functions/paremeters.md

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-07 17:34:59 +00:00
Micha Reiser
6cc2d02dfa
[red-knot] Support stub packages (#17204)
## Summary

This PR adds support for stub packages, except for partial stub packages
(a stub package is always considered non-partial).

I read the specification at
[typing.python.org/en/latest/spec/distributing.html#stub-only-packages](https://typing.python.org/en/latest/spec/distributing.html#stub-only-packages)
but I found it lacking some details, especially on how to handle
namespace packages or when the regular and stub packages disagree on
whether they're namespace packages. I tried to document my decisions in
the mdtests where the specification isn't clear and compared the
behavior to Pyright.

Mypy seems to only support stub packages in the venv folder. At least,
it never picked up my stub packages otherwise. I decided not to spend
too much time fighting mypyp, which is why I focused the comparison
around Pyright

Closes https://github.com/astral-sh/ruff/issues/16612

## Test plan

Added mdtests
2025-04-07 14:40:50 +02:00
Alex Waygood
81cf860dc8
[red-knot] Add a couple more tests for * imports (#17270)
## Summary

Some more edge cases that I thought of while working on integrating
knowledge of statically known branches into the `*`-import machinery

## Test Plan

`cargo test -p red_knot_python_semantic`
2025-04-07 11:12:28 +00:00
Alex Waygood
ac5d220d75
[red-knot] Fix python setting in mdtests, and rewrite a site-packages test as an mdtest (#17222)
## Summary

This PR does the following things:
- Fixes the `python` configuration setting for mdtest (added in
https://github.com/astral-sh/ruff/pull/17221) so that it expects a path
pointing to a venv's `sys.prefix` variable rather than the a path
pointing to the venv's `site-packages` subdirectory. This brings the
`python` setting in mdtest in sync with our CLI `--python` flag.
- Tweaks mdtest so that it automatically creates a valid `pyvenv.cfg`
file for you if you don't specify one. This makes it much more ergonomic
to write an mdtest with a custom `python` setting: red-knot will reject
a `python` setting that points to a directory that doesn't have a
`pyvenv.cfg` file in it
- Tweaks mdtest so that it doesn't check a custom `pyvenv.cfg` as Python
source code if you _do_ add a custom `pyvenv.cfg` file for your mock
virtual environment in an mdtest. (You get a lot of diagnostics about
Python syntax errors in the `pyvenv.cfg` file, otherwise!)
- Rewrites the test added in
https://github.com/astral-sh/ruff/pull/17178 as an mdtest, and deletes
the original test that was added in that PR

## Test Plan

I verified that the new mdtest fails if I revert the changes to
`resolver.rs` that were added in
https://github.com/astral-sh/ruff/pull/17178
2025-04-06 18:24:32 +01:00
Matthew Mckee
73a9974d8a
Fix CallableTypeOf display signature (#17235) 2025-04-06 18:12:52 +01:00
cake-monotone
7e6d3838bd
[red-knot] Add cycle handling to narrow constraints queries (#17209)
## Summary

This PR fixes the cycle issue that was causing problems in the `support
super` PR.

### Affected queries
- `all_narrowing_constraints_for_expression`
- `all_negative_narrowing_constraints_for_expression`


--

Additionally, `bidict` and `werkzeug` have been added to the
project-selection list in `mypy_primer`.
This PR also addresses the panics that occurred while analyzing those
packages:

- `bidict`: panic triggered by
`all_narrowing_constraints_for_expression`
- `werkzeug`: panic triggered by
`all_negative_narrowing_constraints_for_expression`

I think the mypy-primer results for this PR can serve as sufficient test
:)
2025-04-04 22:26:20 -07:00
David Peter
1a6a10b30f
[red-knot] Empty tuple is always-falsy (#17213)
Some checks are pending
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
## Summary

Fix assignability of `tuple[()]` to `AlwaysFalsy`.

closes #17202 

## Test Plan

Ran the property tests for a while
2025-04-04 22:00:28 +02:00
Micha Reiser
ffa824e037
[red-knot] Add Type.definition method (#17153)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
## Summary

This is a follow up to the goto type definition PR. Specifically, that
we want to avoid exposing too many semantic model internals publicly.

I want to get some feedback on the approach taken. I think it goes into
the right direction but I'm not super happy with it.
The basic idea is that we add a `Type::definition` method which does the
"goto type definition". The parts that I think make it awkward:

* We can't directly return `Definition` because we don't create a
`Definition` for modules (but we could?). Although I think it makes
sense to possibly have a more public wrapper type anyway?
* It doesn't handle unions and intersections. Mainly because not all
elements in an intersection may have a definition and we only want to
show a navigation target for intersections if there's only a single
positive element (besides maybe `Unknown`).


An alternative design or an addition to this design is to introduce a
`SemanticAnalysis(Db)` struct that has methods like
`type_definition(&self, type)` which explicitly exposes the methods we
want. I don't feel comfortable design this API yet because it's unclear
how fine granular it has to be (and if it is very fine granular,
directly using `Type` might be better after all)


## Test Plan

`cargo test`
2025-04-04 10:56:20 +02:00
Carl Meyer
bf0306887a
[red-knot] don't remove negations when simplifying constrained typevars (#17189)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
For two non-disjoint types `P` and `Q`, the simplification of `(P | Q) &
~Q` is not `P`, but `P & ~Q`. In other words, the non-empty set `P & Q`
is also excluded from the type.

The same applies for a constrained typevar `[T: (P, Q)]`: `T & ~Q`
should simplify to `P & ~Q`, not just `P`.

Implementing this is actually purely a matter of removing code from the
constrained typevar simplification logic; we just need to not bother
removing the negations. If the negations are actually redundant (because
the constraint types are disjoint), normal intersection simplification
will already eliminate them (as shown in the added test.)
2025-04-03 16:30:57 -07:00
Micha Reiser
e7684d3493
Enable overindented docs lint (#17182)
## Summary

It turns out that `a.` isn't a list format supported by rustdoc. I
changed the documentation to use `1.`, `2.` instead.

## Test Plan

`cargo clippy`
2025-04-03 20:27:11 +01:00
Douglas Creager
64e7e1aa64
[red-knot] Add Type::TypeVar variant (#17102)
This adds a new `Type` variant for holding an instance of a typevar
inside of a generic function or class. We don't handle specializing the
typevars yet, but this should implement most of the typing rules for
inside the generic function/class, where we don't know yet which
specific type the typevar will be specialized to.

This PR does _not_ yet handle the constraint that multiple occurrences
of the typevar must be specialized to the _same_ time. (There is an
existing test case for this in `generics/functions.md` which is still
marked as TODO.)

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-03 14:36:29 -04:00
Micha Reiser
8a4158c5f8
Upgrade to Rust 1.86 and bump MSRV to 1.84 (#17171)
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

I decided to disable the new
[`needless_continue`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue)
rule because I often found the explicit `continue` more readable over an
empty block or having to invert the condition of an other branch.


## Test Plan

`cargo test`

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-04-03 15:59:44 +00:00
David Peter
fedd982fd5
[red-knot] Avoid unresolved-reference in unreachable code (#17169)
## Summary

This PR changes the inferred type for symbols in unreachable sections of
code to `Never` (instead of reporting them as unbound), in order to
silence false positive diagnostics. See the lengthy comment in the code
for further details.

## Test Plan

- Updated Markdown tests.
- Manually verified a couple of ecosystem diagnostic changes.
2025-04-03 16:52:11 +02:00
Alex Waygood
a1eb834a5f
Fix relative import resolution in site-packages packages when the site-packages search path is a subdirectory of the first-party search path (#17178)
## Summary

If a package in `site-packages` had this directory structure:

```py
# bar/__init__.py
from .a import A

# bar/a.py
class A: ...
```

then we would fail to resolve the `from .a import A` import _if_ (as is
usually the case!) the `site-packages` search path was located inside a
`.venv` directory that was a subdirectory of the project's first-party
search path. The reason for this is a bug in `file_to_module` in the
module resolver. In this loop, we would identify that
`/project_root/.venv/lib/python3.13/site-packages/foo/__init__.py` can
be turned into a path relative to the first-party search path
(`/project_root`):


6e2b8f9696/crates/red_knot_python_semantic/src/module_resolver/resolver.rs (L101-L110)

but we'd then try to turn the relative path
(.venv/lib/python3.13/site-packages/foo/__init__.py`) into a module
path, realise that it wasn't a valid module path... and therefore
immediately `break` out of the loop before trying any other search paths
(such as the `site-packages` search path).

This bug was originally reported on Discord by @MatthewMckee4.

## Test Plan

I added a unit test for `file_to_module` in `resolver.rs`, and an
integration test that shows we can now resolve the import correctly in
`infer.rs`.
2025-04-03 15:48:05 +01:00
Alex Waygood
ca0cce3f9c
[red-knot] Fix more [redundant-cast] false positives (#17170)
Fixes #17164. Simply checking whether one type is gradually equivalent
to another is too simplistic here: `Any` is gradually equivalent to
`Todo`, but we should permit users to cast from `Todo` or `Unknown` to
`Any` without complaining about it. This changes our logic so that we
only complain about redundant casts if:
- the two types are exactly equal (when normalized) OR they are
equivalent (we'll still complain about `Any -> Any` casts, and about
`Any | str | int` -> `str | int | Any` casts, since their normalized
forms are exactly equal, even though the type is not fully static -- and
therefore does not participate in equivalence relations)
- AND the casted type does not contain `Todo`
2025-04-03 15:00:00 +01:00
David Peter
3f00010a7a
[red-knot] Three-argument type-calls take 'str' as the first argument (#17168)
## Summary

Similar to #17163, a minor fix in the signature of `type(…)`.

## Test Plan

New MD tests
2025-04-03 15:45:08 +02:00
Alex Waygood
62f8d855d2
[red-knot] Improve Debug implementation for semantic_index::SymbolTable (#17172)
## Summary

`dbg!`ing a `SymbolTable` is currently very noisy due to the
`symbols_by_name` field, which doesn't tell you very much at all. The
noisiness makes debugging difficult. This PR removes the
`symbols_by_name` field from the `Debug` implementation.

## Test Plan

`dbg!` output before of the `builtins.pyi` global-scope symbol table:

<details>

```
[crates/red_knot_python_semantic/src/symbol.rs:633:5] symbol_table(db, scope) = SymbolTable {
    symbols: [
        Symbol {
            name: Name("_ast"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_sitebuiltins"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_typeshed"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("sys"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("types"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("dict_items"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("dict_keys"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("dict_values"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("AnyStr_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ConvertibleToFloat"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ConvertibleToInt"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("FileDescriptorOrPath"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OpenBinaryMode"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OpenBinaryModeReading"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OpenBinaryModeUpdating"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OpenBinaryModeWriting"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OpenTextMode"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ReadableBuffer"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsAdd"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsAiter"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsAnext"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsDivMod"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsFlush"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsIter"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsKeysAndGetItem"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsLenAndGetItem"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsNext"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsRAdd"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsRDivMod"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsRichComparison"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsRichComparisonT"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsWrite"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Awaitable"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Callable"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Iterable"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Iterator"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("MutableSet"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Reversible"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("AbstractSet"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Sized"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BufferedRandom"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BufferedReader"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BufferedWriter"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("FileIO"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TextIOWrapper"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("CellType"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("CodeType"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TracebackType"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("IO"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Any"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BinaryIO"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ClassVar"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Generic"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Mapping"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("MutableMapping"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("MutableSequence"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Protocol"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Sequence"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsAbs"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsBytes"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsComplex"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsFloat"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsIndex"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TypeVar"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("final"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("overload"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("type_check_only"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Concatenate"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Literal"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("LiteralString"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ParamSpec"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Self"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TypeAlias"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TypeGuard"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TypeIs"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TypeVarTuple"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("deprecated"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("GenericAlias"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_T"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("int"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_I"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T_contra"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_R_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_KT"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_VT"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_S"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T1"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T2"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T3"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T4"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T5"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_SupportsNextT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_SupportsAnextT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_AwaitableT"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_AwaitableT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_P"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_StartT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_StopT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_StepT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("object"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("staticmethod"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("classmethod"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("type"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("super"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_PositiveInteger"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_NegativeInteger"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_LiteralInteger"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("float"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("complex"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_FormatMapMapping"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_TranslateTable"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("str"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("bytes"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("bytearray"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_IntegerFormats"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("memoryview"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("bool"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("slice"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("tuple"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("function"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("list"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("dict"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("set"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("frozenset"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("enumerate"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("range"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("property"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_NotImplementedType"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("NotImplemented"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("abs"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("all"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("any"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ascii"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("bin"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("breakpoint"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("callable"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("chr"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_PathLike"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("aiter"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsSynchronousAnext"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("anext"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("compile"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("copyright"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("credits"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("delattr"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("dir"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("divmod"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("eval"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("exec"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("exit"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("filter"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("format"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("getattr"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("globals"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("hasattr"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("hash"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("help"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("hex"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("id"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("input"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_GetItemIterable"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("iter"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_ClassInfo"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("isinstance"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("issubclass"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("len"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("license"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("locals"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("map"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("max"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("min"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("next"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("oct"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_Opener"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("open"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ord"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsWriteAndFlush"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("print"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_E_contra"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_M_contra"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_SupportsPow2"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsPow3NoneOnly"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsPow3"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsSomeKindOfPow"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("pow"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("quit"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("reversed"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("repr"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsRound1"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsRound2"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("round"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("setattr"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("sorted"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_AddableT1"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_AddableT2"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_SupportsSumWithNoDefaultGiven"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsSumNoDefaultT"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("sum"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("vars"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("zip"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("__import__"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("__build_class__"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("EllipsisType"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ellipsis"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Ellipsis"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BaseException"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("GeneratorExit"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("KeyboardInterrupt"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SystemExit"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Exception"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("StopIteration"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OSError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("EnvironmentError"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("IOError"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("WindowsError"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("ArithmeticError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("AssertionError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("AttributeError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BufferError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("EOFError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ImportError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("LookupError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("MemoryError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("NameError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ReferenceError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("RuntimeError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("StopAsyncIteration"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SyntaxError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SystemError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TypeError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ValueError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("FloatingPointError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OverflowError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ZeroDivisionError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ModuleNotFoundError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("IndexError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("KeyError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UnboundLocalError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BlockingIOError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ChildProcessError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ConnectionError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BrokenPipeError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ConnectionAbortedError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ConnectionRefusedError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ConnectionResetError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("FileExistsError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("FileNotFoundError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("InterruptedError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("IsADirectoryError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("NotADirectoryError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("PermissionError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ProcessLookupError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TimeoutError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("NotImplementedError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("RecursionError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("IndentationError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TabError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UnicodeError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UnicodeDecodeError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UnicodeEncodeError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UnicodeTranslateError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Warning"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UserWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("DeprecationWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SyntaxWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("RuntimeWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("FutureWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("PendingDeprecationWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ImportWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UnicodeWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BytesWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ResourceWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("EncodingWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_BaseExceptionT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_BaseExceptionT"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_ExceptionT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_ExceptionT"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("BaseExceptionGroup"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ExceptionGroup"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("PythonFinalizationError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
    ],
    symbols_by_name: {
        ScopedSymbolId(
            235,
        ): (),
        ScopedSymbolId(
            267,
        ): (),
        ScopedSymbolId(
            86,
        ): (),
        ScopedSymbolId(
            22,
        ): (),
        ScopedSymbolId(
            182,
        ): (),
        ScopedSymbolId(
            213,
        ): (),
        ScopedSymbolId(
            252,
        ): (),
        ScopedSymbolId(
            177,
        ): (),
        ScopedSymbolId(
            173,
        ): (),
        ScopedSymbolId(
            108,
        ): (),
        ScopedSymbolId(
            122,
        ): (),
        ScopedSymbolId(
            118,
        ): (),
        ScopedSymbolId(
            197,
        ): (),
        ScopedSymbolId(
            69,
        ): (),
        ScopedSymbolId(
            134,
        ): (),
        ScopedSymbolId(
            52,
        ): (),
        ScopedSymbolId(
            248,
        ): (),
        ScopedSymbolId(
            168,
        ): (),
        ScopedSymbolId(
            2,
        ): (),
        ScopedSymbolId(
            129,
        ): (),
        ScopedSymbolId(
            5,
        ): (),
        ScopedSymbolId(
            18,
        ): (),
        ScopedSymbolId(
            150,
        ): (),
        ScopedSymbolId(
            9,
        ): (),
        ScopedSymbolId(
            16,
        ): (),
        ScopedSymbolId(
            205,
        ): (),
        ScopedSymbolId(
            246,
        ): (),
        ScopedSymbolId(
            68,
        ): (),
        ScopedSymbolId(
            93,
        ): (),
        ScopedSymbolId(
            189,
        ): (),
        ScopedSymbolId(
            161,
        ): (),
        ScopedSymbolId(
            64,
        ): (),
        ScopedSymbolId(
            124,
        ): (),
        ScopedSymbolId(
            229,
        ): (),
        ScopedSymbolId(
            94,
        ): (),
        ScopedSymbolId(
            202,
        ): (),
        ScopedSymbolId(
            67,
        ): (),
        ScopedSymbolId(
            120,
        ): (),
        ScopedSymbolId(
            219,
        ): (),
        ScopedSymbolId(
            12,
        ): (),
        ScopedSymbolId(
            20,
        ): (),
        ScopedSymbolId(
            79,
        ): (),
        ScopedSymbolId(
            11,
        ): (),
        ScopedSymbolId(
            157,
        ): (),
        ScopedSymbolId(
            216,
        ): (),
        ScopedSymbolId(
            231,
        ): (),
        ScopedSymbolId(
            239,
        ): (),
        ScopedSymbolId(
            140,
        ): (),
        ScopedSymbolId(
            36,
        ): (),
        ScopedSymbolId(
            13,
        ): (),
        ScopedSymbolId(
            184,
        ): (),
        ScopedSymbolId(
            204,
        ): (),
        ScopedSymbolId(
            70,
        ): (),
        ScopedSymbolId(
            259,
        ): (),
        ScopedSymbolId(
            96,
        ): (),
        ScopedSymbolId(
            111,
        ): (),
        ScopedSymbolId(
            72,
        ): (),
        ScopedSymbolId(
            247,
        ): (),
        ScopedSymbolId(
            101,
        ): (),
        ScopedSymbolId(
            242,
        ): (),
        ScopedSymbolId(
            261,
        ): (),
        ScopedSymbolId(
            263,
        ): (),
        ScopedSymbolId(
            214,
        ): (),
        ScopedSymbolId(
            62,
        ): (),
        ScopedSymbolId(
            166,
        ): (),
        ScopedSymbolId(
            244,
        ): (),
        ScopedSymbolId(
            257,
        ): (),
        ScopedSymbolId(
            133,
        ): (),
        ScopedSymbolId(
            112,
        ): (),
        ScopedSymbolId(
            87,
        ): (),
        ScopedSymbolId(
            90,
        ): (),
        ScopedSymbolId(
            117,
        ): (),
        ScopedSymbolId(
            158,
        ): (),
        ScopedSymbolId(
            162,
        ): (),
        ScopedSymbolId(
            230,
        ): (),
        ScopedSymbolId(
            154,
        ): (),
        ScopedSymbolId(
            255,
        ): (),
        ScopedSymbolId(
            35,
        ): (),
        ScopedSymbolId(
            39,
        ): (),
        ScopedSymbolId(
            138,
        ): (),
        ScopedSymbolId(
            190,
        ): (),
        ScopedSymbolId(
            21,
        ): (),
        ScopedSymbolId(
            66,
        ): (),
        ScopedSymbolId(
            181,
        ): (),
        ScopedSymbolId(
            7,
        ): (),
        ScopedSymbolId(
            236,
        ): (),
        ScopedSymbolId(
            251,
        ): (),
        ScopedSymbolId(
            152,
        ): (),
        ScopedSymbolId(
            227,
        ): (),
        ScopedSymbolId(
            78,
        ): (),
        ScopedSymbolId(
            55,
        ): (),
        ScopedSymbolId(
            61,
        ): (),
        ScopedSymbolId(
            253,
        ): (),
        ScopedSymbolId(
            47,
        ): (),
        ScopedSymbolId(
            65,
        ): (),
        ScopedSymbolId(
            153,
        ): (),
        ScopedSymbolId(
            104,
        ): (),
        ScopedSymbolId(
            74,
        ): (),
        ScopedSymbolId(
            107,
        ): (),
        ScopedSymbolId(
            149,
        ): (),
        ScopedSymbolId(
            98,
        ): (),
        ScopedSymbolId(
            155,
        ): (),
        ScopedSymbolId(
            169,
        ): (),
        ScopedSymbolId(
            180,
        ): (),
        ScopedSymbolId(
            237,
        ): (),
        ScopedSymbolId(
            146,
        ): (),
        ScopedSymbolId(
            15,
        ): (),
        ScopedSymbolId(
            243,
        ): (),
        ScopedSymbolId(
            17,
        ): (),
        ScopedSymbolId(
            136,
        ): (),
        ScopedSymbolId(
            80,
        ): (),
        ScopedSymbolId(
            44,
        ): (),
        ScopedSymbolId(
            228,
        ): (),
        ScopedSymbolId(
            60,
        ): (),
        ScopedSymbolId(
            245,
        ): (),
        ScopedSymbolId(
            193,
        ): (),
        ScopedSymbolId(
            264,
        ): (),
        ScopedSymbolId(
            268,
        ): (),
        ScopedSymbolId(
            58,
        ): (),
        ScopedSymbolId(
            258,
        ): (),
        ScopedSymbolId(
            279,
        ): (),
        ScopedSymbolId(
            113,
        ): (),
        ScopedSymbolId(
            135,
        ): (),
        ScopedSymbolId(
            240,
        ): (),
        ScopedSymbolId(
            85,
        ): (),
        ScopedSymbolId(
            186,
        ): (),
        ScopedSymbolId(
            100,
        ): (),
        ScopedSymbolId(
            187,
        ): (),
        ScopedSymbolId(
            106,
        ): (),
        ScopedSymbolId(
            73,
        ): (),
        ScopedSymbolId(
            223,
        ): (),
        ScopedSymbolId(
            49,
        ): (),
        ScopedSymbolId(
            83,
        ): (),
        ScopedSymbolId(
            77,
        ): (),
        ScopedSymbolId(
            43,
        ): (),
        ScopedSymbolId(
            274,
        ): (),
        ScopedSymbolId(
            46,
        ): (),
        ScopedSymbolId(
            151,
        ): (),
        ScopedSymbolId(
            217,
        ): (),
        ScopedSymbolId(
            178,
        ): (),
        ScopedSymbolId(
            278,
        ): (),
        ScopedSymbolId(
            132,
        ): (),
        ScopedSymbolId(
            6,
        ): (),
        ScopedSymbolId(
            174,
        ): (),
        ScopedSymbolId(
            99,
        ): (),
        ScopedSymbolId(
            196,
        ): (),
        ScopedSymbolId(
            109,
        ): (),
        ScopedSymbolId(
            128,
        ): (),
        ScopedSymbolId(
            123,
        ): (),
        ScopedSymbolId(
            102,
        ): (),
        ScopedSymbolId(
            116,
        ): (),
        ScopedSymbolId(
            172,
        ): (),
        ScopedSymbolId(
            32,
        ): (),
        ScopedSymbolId(
            105,
        ): (),
        ScopedSymbolId(
            241,
        ): (),
        ScopedSymbolId(
            95,
        ): (),
        ScopedSymbolId(
            206,
        ): (),
        ScopedSymbolId(
            209,
        ): (),
        ScopedSymbolId(
            198,
        ): (),
        ScopedSymbolId(
            81,
        ): (),
        ScopedSymbolId(
            170,
        ): (),
        ScopedSymbolId(
            171,
        ): (),
        ScopedSymbolId(
            8,
        ): (),
        ScopedSymbolId(
            276,
        ): (),
        ScopedSymbolId(
            1,
        ): (),
        ScopedSymbolId(
            212,
        ): (),
        ScopedSymbolId(
            222,
        ): (),
        ScopedSymbolId(
            33,
        ): (),
        ScopedSymbolId(
            144,
        ): (),
        ScopedSymbolId(
            194,
        ): (),
        ScopedSymbolId(
            125,
        ): (),
        ScopedSymbolId(
            89,
        ): (),
        ScopedSymbolId(
            38,
        ): (),
        ScopedSymbolId(
            51,
        ): (),
        ScopedSymbolId(
            19,
        ): (),
        ScopedSymbolId(
            163,
        ): (),
        ScopedSymbolId(
            0,
        ): (),
        ScopedSymbolId(
            211,
        ): (),
        ScopedSymbolId(
            3,
        ): (),
        ScopedSymbolId(
            226,
        ): (),
        ScopedSymbolId(
            121,
        ): (),
        ScopedSymbolId(
            148,
        ): (),
        ScopedSymbolId(
            232,
        ): (),
        ScopedSymbolId(
            262,
        ): (),
        ScopedSymbolId(
            260,
        ): (),
        ScopedSymbolId(
            91,
        ): (),
        ScopedSymbolId(
            270,
        ): (),
        ScopedSymbolId(
            269,
        ): (),
        ScopedSymbolId(
            225,
        ): (),
        ScopedSymbolId(
            191,
        ): (),
        ScopedSymbolId(
            115,
        ): (),
        ScopedSymbolId(
            28,
        ): (),
        ScopedSymbolId(
            220,
        ): (),
        ScopedSymbolId(
            164,
        ): (),
        ScopedSymbolId(
            250,
        ): (),
        ScopedSymbolId(
            137,
        ): (),
        ScopedSymbolId(
            141,
        ): (),
        ScopedSymbolId(
            24,
        ): (),
        ScopedSymbolId(
            54,
        ): (),
        ScopedSymbolId(
            45,
        ): (),
        ScopedSymbolId(
            188,
        ): (),
        ScopedSymbolId(
            75,
        ): (),
        ScopedSymbolId(
            40,
        ): (),
        ScopedSymbolId(
            234,
        ): (),
        ScopedSymbolId(
            30,
        ): (),
        ScopedSymbolId(
            41,
        ): (),
        ScopedSymbolId(
            127,
        ): (),
        ScopedSymbolId(
            185,
        ): (),
        ScopedSymbolId(
            145,
        ): (),
        ScopedSymbolId(
            23,
        ): (),
        ScopedSymbolId(
            238,
        ): (),
        ScopedSymbolId(
            143,
        ): (),
        ScopedSymbolId(
            167,
        ): (),
        ScopedSymbolId(
            110,
        ): (),
        ScopedSymbolId(
            25,
        ): (),
        ScopedSymbolId(
            31,
        ): (),
        ScopedSymbolId(
            57,
        ): (),
        ScopedSymbolId(
            195,
        ): (),
        ScopedSymbolId(
            221,
        ): (),
        ScopedSymbolId(
            218,
        ): (),
        ScopedSymbolId(
            37,
        ): (),
        ScopedSymbolId(
            71,
        ): (),
        ScopedSymbolId(
            50,
        ): (),
        ScopedSymbolId(
            176,
        ): (),
        ScopedSymbolId(
            179,
        ): (),
        ScopedSymbolId(
            200,
        ): (),
        ScopedSymbolId(
            266,
        ): (),
        ScopedSymbolId(
            277,
        ): (),
        ScopedSymbolId(
            119,
        ): (),
        ScopedSymbolId(
            84,
        ): (),
        ScopedSymbolId(
            114,
        ): (),
        ScopedSymbolId(
            165,
        ): (),
        ScopedSymbolId(
            271,
        ): (),
        ScopedSymbolId(
            280,
        ): (),
        ScopedSymbolId(
            256,
        ): (),
        ScopedSymbolId(
            249,
        ): (),
        ScopedSymbolId(
            88,
        ): (),
        ScopedSymbolId(
            27,
        ): (),
        ScopedSymbolId(
            139,
        ): (),
        ScopedSymbolId(
            265,
        ): (),
        ScopedSymbolId(
            4,
        ): (),
        ScopedSymbolId(
            53,
        ): (),
        ScopedSymbolId(
            29,
        ): (),
        ScopedSymbolId(
            130,
        ): (),
        ScopedSymbolId(
            42,
        ): (),
        ScopedSymbolId(
            76,
        ): (),
        ScopedSymbolId(
            147,
        ): (),
        ScopedSymbolId(
            156,
        ): (),
        ScopedSymbolId(
            208,
        ): (),
        ScopedSymbolId(
            273,
        ): (),
        ScopedSymbolId(
            183,
        ): (),
        ScopedSymbolId(
            224,
        ): (),
        ScopedSymbolId(
            97,
        ): (),
        ScopedSymbolId(
            233,
        ): (),
        ScopedSymbolId(
            82,
        ): (),
        ScopedSymbolId(
            142,
        ): (),
        ScopedSymbolId(
            254,
        ): (),
        ScopedSymbolId(
            131,
        ): (),
        ScopedSymbolId(
            63,
        ): (),
        ScopedSymbolId(
            48,
        ): (),
        ScopedSymbolId(
            215,
        ): (),
        ScopedSymbolId(
            103,
        ): (),
        ScopedSymbolId(
            14,
        ): (),
        ScopedSymbolId(
            92,
        ): (),
        ScopedSymbolId(
            207,
        ): (),
        ScopedSymbolId(
            275,
        ): (),
        ScopedSymbolId(
            160,
        ): (),
        ScopedSymbolId(
            26,
        ): (),
        ScopedSymbolId(
            56,
        ): (),
        ScopedSymbolId(
            34,
        ): (),
        ScopedSymbolId(
            272,
        ): (),
        ScopedSymbolId(
            59,
        ): (),
        ScopedSymbolId(
            126,
        ): (),
        ScopedSymbolId(
            159,
        ): (),
        ScopedSymbolId(
            199,
        ): (),
        ScopedSymbolId(
            175,
        ): (),
        ScopedSymbolId(
            192,
        ): (),
        ScopedSymbolId(
            201,
        ): (),
        ScopedSymbolId(
            203,
        ): (),
        ScopedSymbolId(
            210,
        ): (),
        ScopedSymbolId(
            10,
        ): (),
    },
}
```

</details>


I checked that with this PR, the second field is gone from the debug
output (I'd paste it in, but it goes over the GitHub comment length
maximum).
2025-04-03 13:37:29 +01:00
David Peter
130339f3d8
[red-knot] Fix str(…) calls (#17163)
## Summary

The existing signature for `str` calls had various problems, one of
which I noticed while looking at some ecosystem projects (`scrapy`,
added as a project to mypy_primer in this PR).

## Test Plan

- New tests for `str(…)` calls.
- Observed reduction of false positives in ecosystem checks
2025-04-03 13:26:32 +02:00
Eric Mark Martin
e50fc049ab
[red-knot] visibility_constraint analysis for match cases (#17077)
## Summary

Add visibility constraint analysis for pattern predicate kinds
`Singleton`, `Or`, and `Class`.

## Test Plan

update conditional/match.md
2025-04-03 11:15:33 +00:00
Dhruv Manilawala
177afabe18
[red-knot] Callable types are disjoint from literals (#17160)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
## Summary

A callable type is disjoint from other literal types. For example,
`Type::StringLiteral` must be an instance of exactly `str`, not a
subclass of `str`, and `str` is not callable. The same applies to other
literal types.

This should hopefully fix #17144, I couldn't produce any failures after
running property tests multiple times.

## Test Plan

Add test cases for disjointness check between callable and other literal
types.

Run property tests multiple times.
2025-04-03 03:38:13 +05:30
Alex Waygood
28c68934a4
[red-knot] Fix inference for pow between two literal integers (#17161)
## Summary

Python `**` works differently to Rust `**`!

## Test Plan

Added an mdtest for various edge cases, and checked in the Python REPL
that we infer the correct type in all the new cases tested.
2025-04-02 21:25:57 +00:00
Alex Waygood
195bb433db
[red-knot] Add GitHub PR annotations when mdtests fail in CI (#17150)
## Summary

This PR adds a CI job that causes GitHub to add annotations to a PR diff
when mdtest assertions fail. For example:

<details>
<summary>Screenshot</summary>


![image](https://github.com/user-attachments/assets/bb2a649b-46ab-429d-a576-b36545940eaf)

</details>

## Motivation

Debugging mdtest failures locally is currently a really nice experience:
- Errors are displayed with pretty colours, which makes them much more
readable
- If you run the test from inside an IDE, you can CTRL-click on a path
and jump directly to the line that had the failing assertion
- If you use
[`mdtest.py`](https://github.com/astral-sh/ruff/blob/main/crates/red_knot_python_semantic/mdtest.py),
you don't even need to recompile anything after changing an assertion in
an mdtest, amd the test results instantly live-update with each change
to the MarkDown file

Debugging mdtest failures in CI is much more unpleasant, however.
Sometimes an error message is just

> [static-assert-error] Argument evaluates to `False`

...which doesn't tell you very much unless you navigate to the line in
question that has the failing mdtest assertion. The line in question
might not even be touched by the PR, and even if it is, it can be hard
to find the line if the PR touches many files. Unlike locally, you can't
click on the error and jump straight to the line that contains the
failing assertion. You also don't get colourised output in CI
(https://github.com/astral-sh/ruff/issues/13939).

GitHub PR annotations should make it really easy to debug why mdtests
are failing on PRs, making PR review much easier.

## Test Plan

I opened a PR to my fork
[here](https://github.com/AlexWaygood/ruff/pull/11/files) with some
bogus changes to an mdtest to show what it looks like when there are
failures in CI and this job has been added. Scroll down to
`crates/red_knot_python_semantic/resources/mdtest/type_properties/is_equivalent_to.md`
on the "files changed" tab for that PR to see the annotations.
2025-04-02 21:51:52 +01:00
Alex Waygood
c2bb5d5250
[red-knot] Fix equivalence of differently ordered unions that contain Callable types (#17145)
## Summary

Fixes https://github.com/astral-sh/ruff/issues/17058.

Equivalent callable types were not understood as equivalent when they
appeared nested inside unions and intersections. This PR fixes that by
ensuring that `Callable` elements nested inside unions, intersections
and tuples have their representations normalized before one union type
is compared with another for equivalence, or before one intersection
type is compared with another for equivalence.

The normalizations applied to a `Callable` type are:
- the type of the default value is stripped from all parameters (only
whether the parameter _has_ a default value is relevant to whether one
`Callable` type is equivalent to another)
- The names of the parameters are stripped from positional-only
parameters, variadic parameters and keyword-variadic parameters
- Unions and intersections that are present (top-level or nested) inside
parameter annotations or return annotations are normalized.

Adding a `CallableType::normalized()` method also allows us to simplify
the implementation of `CallableType::is_equivalent_to()`.

### Should these normalizations be done eagerly as part of a
`CallableType` constructor?

I considered this. It's something that we could still consider doing in
the future; this PR doesn't rule it out as a possibility. However, I
didn't pursue it for now, for several reasons:
1. Our current `Display` implementation doesn't handle well the
possibility that a parameter might not have a name or an annotated type.
Callable types with parameters like this would be displayed as follows:
   ```py
   (, ,) -> None: ...
   ```

That's fixable! It could easily become something like `(Unknown,
Unknown) -> None: ...`. But it also illustrates that we probably want to
retain the parameter names when displaying the signature of a `lambda`
function if you're hovering over a reference to the lambda in an IDE.
Currently we don't have a `LambdaType` struct for representing `lambda`
functions; if we wanted to eagerly normalize signatures when creating
`CallableType`s, we'd probably have to add a `LambdaType` struct so that
we would retain the full signature of a `lambda` function, rather than
representing it as an eagerly simplified `CallableType`.
2. In order to ensure that it's impossible to create `CallableType`s
without the parameters being normalized, I'd either have to create an
alternative `SimplifiedSignature` struct (which would duplicate a lot of
code), or move `CallableType` to a new module so that the only way of
constructing a `CallableType` instance would be via a constructor method
that performs the normalizations eagerly on the callable's signature.
Again, this isn't a dealbreaker, and I think it's still an option, but
it would be a lot of churn, and it didn't seem necessary for now. Doing
it this way, at least to start with, felt like it would create a diff
that's easier to review and felt like it would create fewer merge
conflicts for others.

## Test Plan

- Added a regression mdtest for
https://github.com/astral-sh/ruff/issues/17058
- Ran `QUICKCHECK_TESTS=1000000 cargo test --release -p
red_knot_python_semantic -- --ignored types::property_tests::stable`
2025-04-02 17:43:34 +00:00
David Peter
cb7dae1e96
[red-knot] Add initial set of tests for unreachable code (#17159)
## Summary

Add an initial set of tests that will eventually document our behavior
around unreachable code. In the last section of this suite, I argue why
we should never type check unreachable sections and never emit any
diagnostics in these sections.
2025-04-02 19:39:44 +02:00
David Peter
af988bf866
[red-knot] Detect division-by-zero in unions and intersections (#17157)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[Knot Playground] Release / publish (push) Waiting to run
## Summary

With this PR, we emit a diagnostic for this case where
previously didn't:
```py
from typing import Literal

def f(m: int, n: Literal[-1, 0, 1]):
    # error: [division-by-zero] "Cannot divide object of type `int` by zero"
    return m / n
```

## Test Plan

New Markdown test
2025-04-02 18:21:27 +02:00