mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 10:23:11 +00:00
![]() ## Summary This mostly fixes #14899 My motivation was similar to the last comment by @sharkdp there. I ran red_knot on a codebase and the most common error was patterns like this failing: ``` def foo(x: str): ... x: Any = ... if isinstance(x, str): foo(x) # Object of type `Any & str` cannot be assigned to parameter 1 (`x`) of function `foo`; expected type `str` ``` The desired behavior is pretty much to ignore Any/Unknown when resolving intersection assignability - `Any & str` should be assignable to `str`, and `str` should be assignable to `str & Any` The fix is actually very similar to the existing code in `is_subtype_of`, we need to correctly handle intersections on either side, while being careful to handle dynamic types as desired. This does not fix the second test case from that issue: ``` static_assert(is_assignable_to(Intersection[Unrelated, Any], Not[tuple[Unrelated, Any]])) ``` but that's misleading because the root cause there has nothing to do with gradual types. I added a simpler test case that also fails: ``` static_assert(is_assignable_to(Unrelated, Not[tuple[Unrelated]])) ``` This is because we don't determine that Unrelated does not subclass from tuple so we can't rule out this relation. If that logic is improved then this fix should also handle the case of the intersection ## Test Plan Added a bunch of is_assignable_to tests, most of which failed before this fix. |
||
---|---|---|
.. | ||
benches | ||
resources | ||
src | ||
Cargo.toml | ||
README.md |
Ruff Benchmarks
The ruff_benchmark
crate benchmarks the linter and the formatter on individual files:
# Run once on the "baseline".
cargo bench -p ruff_benchmark -- --save-baseline=main
# Compare against the "baseline".
cargo bench -p ruff_benchmark -- --baseline=main
# Run the lexer benchmarks.
cargo bench -p ruff_benchmark lexer -- --baseline=main
See CONTRIBUTING.md on how to use these benchmarks.