Commit Graph

12775 Commits

Author SHA1 Message Date
Dylan d363d49ab7
[`flake8-bugbear`] Skip `B905` and `B912` if <2 iterables and no starred arguments (#20998)
Closes #20997

This will _decrease_ the number of diagnostics emitted for
[zip-without-explicit-strict
(B905)](https://docs.astral.sh/ruff/rules/zip-without-explicit-strict/#zip-without-explicit-strict-b905),
since previously it triggered on any `zip` call no matter the number of
arguments. It may _increase_ the number of diagnostics for
[map-without-explicit-strict
(B912)](https://docs.astral.sh/ruff/rules/map-without-explicit-strict/#map-without-explicit-strict-b912)
since it will now trigger on a single starred argument where before it
would not. However, the latter rule is in `preview` so this is
acceptable.

Note - we do not need to make any changes to
[batched-without-explicit-strict
(B911)](https://docs.astral.sh/ruff/rules/batched-without-explicit-strict/#batched-without-explicit-strict-b911)
since that just takes a single iterable.

I am doing this in one PR rather than two because we should keep the
behavior of these rules consistent with one another.

For review: apologies for the unreadability of the snapshot for `B905`.
Unfortunately I saw no way of keeping a small diff and a correct fixture
(the fixture labeled a whole block as `# Error` whereas now several in
the block became `# Ok`).Probably simplest to just view the actual
snapshot - it's relatively small.
2025-10-20 18:35:32 -05:00
Dylan 281ae8eb34
[`pyupgrade`] Always parenthesize assignment expressions in fix for `f-string` (`UP032`) (#21003)
Closes #21000
2025-10-20 18:34:02 -05:00
renovate[bot] d61902c89f
Update dependency vite to v7.0.8 (#21007)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [vite](https://vite.dev)
([source](https://redirect.github.com/vitejs/vite/tree/HEAD/packages/vite))
| [`7.0.7` ->
`7.0.8`](https://renovatebot.com/diffs/npm/vite/7.0.7/7.0.8) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/vite/7.0.8?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vite/7.0.7/7.0.8?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

> [!WARNING]
> Some dependencies could not be looked up. Check the Dependency
Dashboard for more information.

### GitHub Vulnerability Alerts

####
[CVE-2025-62522](https://redirect.github.com/vitejs/vite/security/advisories/GHSA-93m4-6634-74q7)

### Summary
Files denied by
[`server.fs.deny`](https://vitejs.dev/config/server-options.html#server-fs-deny)
were sent if the URL ended with `\` when the dev server is running on
Windows.

### Impact
Only apps that match the following conditions are affected:

- explicitly exposes the Vite dev server to the network (using --host or
[`server.host` config
option](https://vitejs.dev/config/server-options.html#server-host))
- running the dev server on Windows

### Details
`server.fs.deny` can contain patterns matching against files (by default
it includes `.env`, `.env.*`, `*.{crt,pem}` as such patterns). These
patterns were able to bypass by using a back slash(`\`). The root cause
is that `fs.readFile('/foo.png/')` loads `/foo.png`.

### PoC
```shell
npm create vite@latest
cd vite-project/
cat "secret" > .env
npm install
npm run dev
curl --request-target /.env\ http://localhost:5173
```
<img width="1593" height="616" alt="image"
src="https://github.com/user-attachments/assets/36212f4e-1d3c-4686-b16f-16b35ca9e175"
/>

---

### Release Notes

<details>
<summary>vitejs/vite (vite)</summary>

###
[`v7.0.8`](https://redirect.github.com/vitejs/vite/releases/tag/v7.0.8)

[Compare
Source](https://redirect.github.com/vitejs/vite/compare/v7.0.7...v7.0.8)

Please refer to
[CHANGELOG.md](https://redirect.github.com/vitejs/vite/blob/v7.0.8/packages/vite/CHANGELOG.md)
for details.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "" (UTC), Automerge - At any time (no
schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/astral-sh/ruff).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNDMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE0My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCIsInNlY3VyaXR5Il19-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-20 16:22:20 -07:00
Robsdedude 511710e1ef
[`flake8-gettext`] Resolve qualified names and built-in bindings (`INT001`, `INT002`, `INT003`) (#19045)
## Summary
Make rules `INT001`, `INT002`, and `INT003` also 
* trigger on qualified names when we're sure the calls are calls to the
`gettext` module. For example
  ```python
  from gettext import gettext as foo
  
foo(f"{'bar'}") # very certain that this is a call to a real `gettext`
function => worth linting
  ```
* trigger on `builtins` bindings
  ```python
  from builtins, gettext
  
  gettext.install("...")  # binds `gettext.gettext` to `builtins._`
  builtins.__dict__["_"] = ...  # also a common pattern

  _(f"{'bar'}")  # should therefore also be linted
  ```

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

## Test Plan

Tests have been added to all three rules.

---------

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
2025-10-20 18:24:55 -04:00
Alex Waygood da04d92ff2
remove `playground/issue.py` (#21002) 2025-10-20 21:00:05 +02:00
ShalokShalom 0f21567405
Add source to testimonial (#20971)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-10-20 19:48:07 +02:00
Micha Reiser be32f8acb1
[ty] Fix inconsistent highlighting of self (#20986) 2025-10-20 19:32:48 +02:00
Takayuki Maeda 1197035c02
[`ty`] Add capabilities check for `clear_diagnostics` (#20989) 2025-10-20 19:31:01 +02:00
Shunsuke Shibayama a7c38eb122
[ty] display variance on hover over type variables (#20900) 2025-10-20 17:28:36 +00:00
Micha Reiser 0520d11a66
[ty] Fix `None`, `True` and `False` highlighting in playground (#20994) 2025-10-20 19:25:08 +02:00
David Peter 54cd9d889d
[ty] Refactor: Use `let`-chains in a few places (#20985) 2025-10-20 18:01:37 +01:00
Alex Waygood 44e678a222
Add `language: python` to several pre-commit hook entries (#20992) 2025-10-20 17:32:02 +01:00
Brent Westbrook 38c074e67d
Catch syntax errors in nested interpolations before Python 3.12 (#20949)
Summary
--

This PR fixes the issue I added in #20867 and noticed in #20930. Cases
like this
cause an error on any Python version:

```py
f"{1:""}"
```

which gave me a false sense of security before. Cases like this are
still
invalid only before 3.12 and weren't flagged after the changes in
#20867:

```py
f'{1: abcd "{'aa'}" }'
           # ^  reused quote
f'{1: abcd "{"\n"}" }'
            # ^  backslash
```

I didn't recognize these as nested interpolations that also need to be
checked
for invalid expressions, so filtering out the whole format spec wasn't
quite
right. And `elements.interpolations()` only iterates over the outermost 
interpolations, not the nested ones.

There's basically no code change in this PR, I just moved the existing
check
from `parse_interpolated_string`, which parses the entire string, to
`parse_interpolated_element`. This kind of seems more natural anyway and
avoids
having to try to recursively visit nested elements after the fact in
`parse_interpolated_string`. So viewing the diff with something like

```
git diff --color-moved --ignore-space-change --color-moved-ws=allow-indentation-change main
```

should make this more clear.

Test Plan
--

New tests
2025-10-20 09:03:13 -04:00
Loïc Riegel c2ae9c7806
feat: 'ruff rule' provides more easily parsable JSON ouput (#20168) 2025-10-20 09:09:51 +02:00
renovate[bot] 5a1201b868
Update Rust crate getrandom to v0.3.4 (#20977)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-10-20 07:00:08 +00:00
Takayuki Maeda 48b50128eb
[`ruff`] Update schemars to v1 (#20942) 2025-10-20 08:59:52 +02:00
renovate[bot] 991e8ed178
Update Rust crate serde to v1.0.228 (#20982)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-20 08:53:07 +02:00
renovate[bot] 0fc5520404
Update Rust crate regex-automata to v0.4.13 (#20981)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-20 08:45:17 +02:00
renovate[bot] b82404f706
Update Rust crate globset to v0.4.17 (#20978)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-20 08:35:32 +02:00
renovate[bot] 4622b8f849
Update Rust crate quote to v1.0.41 (#20980)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-20 08:33:26 +02:00
renovate[bot] bb3a88cdd5
Update Rust crate clap to v4.5.49 (#20976)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-20 08:33:09 +02:00
renovate[bot] 029a7aa200
Update Rust crate snapbox to v0.6.22 (#20983)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-20 08:32:48 +02:00
Alex Waygood 590ce9d9ed
Use uv more in CI workflows (#20968)
## Summary

More dogfooding of our own tools.

I didn't touch the build-binaries workflow (it's scary) or the
publish-docs workflow (which doesn't run on PRs) or the ruff-lsp job in
the ci.yaml workflow (ruff-lsp is deprecated; it doesn't seem worth
making changes there).

## Test Plan

CI on this PR
2025-10-19 14:59:10 +01:00
Renkai Ge 0b8de723c6
Refactor format tests to use CliTest helper (#20953)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-10-19 10:25:21 +00:00
Shunsuke Shibayama 36d4b02fa9
[ty] fix non-deterministic overload function inference (#20966) 2025-10-19 12:13:10 +02:00
Alex Waygood 1f8297cfe6
[ty] Improve error messages for unresolved attribute diagnostics (#20963)
## Summary

- Type checkers (and type-checker authors) think in terms of types, but
I think most Python users think in terms of values. Rather than saying
that a _type_ `X` "has no attribute `foo`" (which I think sounds strange
to many users), say that "an object of type `X` has no attribute `foo`"
- Special-case certain types so that the diagnostic messages read more
like normal English: rather than saying "Type `<class 'Foo'>` has no
attribute `bar`" or "Object of type `<class 'Foo'>` has no attribute
`bar`", just say "Class `Foo` has no attribute `bar`"

## Test Plan

Mdtests and snapshots updated
2025-10-19 10:58:25 +01:00
Takayuki Maeda b6b96d75eb
[`ruff`] Use DiagnosticTag for more pyflakes and panda rules (#20801) 2025-10-19 11:07:16 +02:00
David Peter 3c229ae58a
[ty] `dataclass_transform`: Support for fields with an `alias` (#20961)
## Summary

closes https://github.com/astral-sh/ty/issues/1385

## Conformance tests

Two false positives removed, as expected.

## Test Plan

New Markdown tests
2025-10-18 18:20:39 +00:00
Alex Waygood 44d9063058
Reduce duplicated logic between the macOS and Windows CI jobs (#20958) 2025-10-18 18:00:55 +01:00
Alex Waygood 09306a1d69
Run py-fuzzer using Python 3.14 in CI (#20957) 2025-10-18 15:42:39 +01:00
Alex Waygood 68c1fa86c8
[ty] Fix panic when attempting to validate the members of a protocol that inherits from a protocol in another module (#20956) 2025-10-18 15:01:46 +01:00
Alex Waygood 16efe53a72
[ty] Fix panic on recursive class definitions in a stub that use constrained type variables (#20955) 2025-10-18 13:02:55 +00:00
Micha Reiser 7532155c9b
[ty] Add suggestion to unknown rule diagnostics, rename `unknown-rule` lint to `ignore-comment-unknown-rule` (#20948) 2025-10-18 12:44:21 +02:00
Bhuminjay Soni 7198e53182
[syntax-errors] Alternative `match` patterns bind different names (#20682)
<!--
Thank you for contributing to Ruff/ty! 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? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->
This PR implements semantic syntax error where alternative patterns bind
different names

## Test Plan

<!-- How was it tested? -->
I have written inline tests as directed in #17412

---------

Signed-off-by: 11happy <soni5happy@gmail.com>
Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-10-17 21:35:48 +00:00
Alex Waygood 8ca2b5555d
Dogfood ty on py-fuzzer in CI (#20946) 2025-10-17 20:30:17 +01:00
David Peter 6d2cf3475f
Only add the actual schema in schemastore PRs (#20947)
Same as https://github.com/astral-sh/ty/pull/1391:

> Last time I ran this script, due to what I assume was a `npm` version
mismatch, the `package-lock.json` file was updated while running `npm
install` in the `schemastore`. Due to the use of `git commit -a`, it was
accidentally included in the commit for the semi-automated schemastore
PR. The solution here is to only add the actual file that we want to
commit.
2025-10-17 21:14:04 +02:00
Shunsuke Shibayama e4384fc212
[ty] impl `VarianceInferable` for `KnownInstanceType` (#20924)
## Summary

Derived from #20900

Implement `VarianceInferable` for `KnownInstanceType` (especially for
`KnownInstanceType::TypeAliasType`).

The variance of a type alias matches its value type. In normal usage,
type aliases are expanded to value types, so the variance of a type
alias can be obtained without implementing this. However, for example,
if we want to display the variance when hovering over a type alias, we
need to be able to obtain the variance of the type alias itself (cf.
#20900).

## Test Plan

I couldn't come up with a way to test this in mdtest, so I'm testing it
in a test submodule at the end of `types.rs`.
I also added a test to `mdtest/generics/pep695/variance.md`, but it
passes without the changes in this PR.
2025-10-17 21:12:19 +02:00
David Peter 6e7ff07065
[ty] Provide completions on `TypeVar`s (#20943)
## Summary

closes https://github.com/astral-sh/ty/issues/1370

## Test Plan

New snapshot tests
2025-10-17 20:05:20 +02:00
Alex Waygood c7e2bfd759
[ty] `continue` and `break` statements outside loops are syntax errors (#20944)
Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-10-17 17:13:40 +00:00
Alex Waygood c424007645
Update usage instructions and lockfile for py-fuzzer script (#20940) 2025-10-17 15:57:17 +01:00
Brent Westbrook 0115fd3757
Avoid reusing nested, interpolated quotes before Python 3.12 (#20930)
## Summary

Fixes #20774 by tracking whether an `InterpolatedStringState` element is
nested inside of another interpolated element. This feels like kind of a
naive fix, so I'm welcome to other ideas. But it resolves the problem in
the issue and clears up the syntax error in the black compatibility
test, without affecting many other cases.

The other affected case is actually interesting too because the
[input](96b156303b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/fstring.py (L707))
is invalid, but the previous quote selection fixed the invalid syntax:

```pycon
Python 3.11.13 (main, Sep  2 2025, 14:20:25) [Clang 20.1.4 ] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> f'{1: abcd "{'aa'}" }'  # input
  File "<stdin>", line 1
    f'{1: abcd "{'aa'}" }'
                  ^^
SyntaxError: f-string: expecting '}'
>>> f'{1: abcd "{"aa"}" }'  # old output
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Invalid format specifier ' abcd "aa" ' for object of type 'int'
>>> f'{1: abcd "{'aa'}" }'  # new output
  File "<stdin>", line 1
    f'{1: abcd "{'aa'}" }'
                  ^^
SyntaxError: f-string: expecting '}'
```

We now preserve the invalid syntax in the input.

Unfortunately, this also seems to be another edge case I didn't consider
in https://github.com/astral-sh/ruff/pull/20867 because we don't flag
this as a syntax error after 0.14.1:

<details><summary>Shell output</summary>
<p>

```
> uvx ruff@0.14.0 check --ignore ALL --target-version py311 - <<EOF
f'{1: abcd "{'aa'}" }'
EOF
invalid-syntax: Cannot reuse outer quote character in f-strings on Python 3.11 (syntax was added in Python 3.12)
 --> -:1:14
  |
1 | f'{1: abcd "{'aa'}" }'
  |              ^
  |

Found 1 error.
> uvx ruff@0.14.1 check --ignore ALL --target-version py311 - <<EOF
f'{1: abcd "{'aa'}" }'
EOF
All checks passed!
> uvx python@3.11 -m ast <<EOF
f'{1: abcd "{'aa'}" }'
EOF
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/home/brent/.local/share/uv/python/cpython-3.11.13-linux-x86_64-gnu/lib/python3.11/ast.py", line 1752, in <module>
    main()
  File "/home/brent/.local/share/uv/python/cpython-3.11.13-linux-x86_64-gnu/lib/python3.11/ast.py", line 1748, in main
    tree = parse(source, args.infile.name, args.mode, type_comments=args.no_type_comments)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/brent/.local/share/uv/python/cpython-3.11.13-linux-x86_64-gnu/lib/python3.11/ast.py", line 50, in parse
    return compile(source, filename, mode, flags,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<stdin>", line 1
    f'{1: abcd "{'aa'}" }'
                  ^^
SyntaxError: f-string: expecting '}'
```

</p>
</details> 


I assumed that was the same `ParseError` as the one caused by
`f"{1:""}"`, but this is a nested interpolation inside of the format
spec.

## Test Plan

New test copied from the black compatibility test. I guess this is a
duplicate now, I started working on this branch before the new black
tests were imported, so I could delete the separate test in our fixtures
if that's preferable.
2025-10-17 08:49:16 -04:00
David Peter cfbd42c22a
[ty] Support `dataclass_transform` for base class models (#20783)
## Summary

Support `dataclass_transform` when used on a (base) class.

## Typing conformance

* The changes in `dataclasses_transform_class.py` look good, just a few
mistakes due to missing `alias` support.
* I didn't look closely at the changes in
`dataclasses_transform_converter.py` since we don't support `converter`
yet.

## Ecosystem impact

The impact looks huge, but it's concentrated on a single project (ibis).
Their setup looks more or less like this:

* the real `Annotatable`:
d7083c2c96/ibis/common/grounds.py (L100-L101)
* the real `DataType`:
d7083c2c96/ibis/expr/datatypes/core.py (L161-L179)
* the real `Array`:
d7083c2c96/ibis/expr/datatypes/core.py (L1003-L1006)


```py
from typing import dataclass_transform

@dataclass_transform()
class Annotatable:
    pass

class DataType(Annotatable):
    nullable: bool = True

class Array[T](DataType):
    value_type: T
```

They expect something like `Array([1, 2])` to work, but ty, pyright,
mypy, and pyrefly would all expect there to be a first argument for the
`nullable` field on `DataType`. I don't really understand on what
grounds they expect the `nullable` field to be excluded from the
signature, but this seems to be the main reason for the new diagnostics
here. Not sure if related, but it looks like their typing setup is not
really complete
(https://github.com/ibis-project/ibis/issues/6844#issuecomment-1868274770,
this thread also mentions `dataclass_transform`).

## Test Plan

Update pre-existing tests.
2025-10-17 14:04:31 +02:00
Mark Z. Ding fc3b341529
[ty] Truncate Literal type display in some situations (#20928) 2025-10-17 11:50:58 +00:00
Alex Waygood baaa8dad3a
[ty] Re-enable fuzzer seeds that are no longer slow (#20937) 2025-10-17 12:29:13 +01:00
Micha Reiser a21cde8a5a
[ty] Fix playground crash for very large files (#20934) 2025-10-17 09:15:33 +02:00
Aria Desires 64edfb6ef6
[ty] add legacy namespace package support (#20897)
Detect legacy namespace packages and treat them like namespace packages
when looking them up as the *parent* of the module we're interested in.
In all other cases treat them like a regular package.

(This PR is coauthored by @MichaReiser in a shared coding session)

Fixes https://github.com/astral-sh/ty/issues/838

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-10-17 03:16:37 +00:00
Ibraheem Ahmed 96b156303b
[ty] Prefer declared type for invariant collection literals (#20927)
## Summary

Prefer the declared type for collection literals, e.g.,
```py
x: list[Any] = [1, "2", (3,)]
reveal_type(x)  # list[Any]
```

This solves a large part of https://github.com/astral-sh/ty/issues/136
for invariant generics, where respecting the declared type is a lot more
important. It also means that annotated dict literals with `dict[_,
Any]` is a way out of https://github.com/astral-sh/ty/issues/1248.
2025-10-16 16:11:28 -04:00
Douglas Creager b0e10a9777
[ty] Don't track inferability via different `Type` variants (#20677)
We have to track whether a typevar appears in a position where it's
inferable or not. In a non-inferable position (in the body of the
generic class or function that binds it), assignability must hold for
every possible specialization of the typevar. In an inferable position,
it only needs to hold for _some_ specialization.
https://github.com/astral-sh/ruff/pull/20093 is working on using
constraint sets to model assignability of typevars, and the constraint
sets that we produce will be the same for inferable vs non-inferable
typevars; what changes is what we _compare_ that constraint set to. (For
a non-inferable typevar, the constraint set must equal the set of valid
specializations; for an inferable typevar, it must not be `never`.)

When I first added support for tracking inferable vs non-inferable
typevars, it seemed like it would be easiest to have separate `Type`
variants for each. The alternative (which lines up with the Δ set in
[POPL15](https://doi.org/10.1145/2676726.2676991)) would be to
explicitly plumb through a list of inferable typevars through our type
property methods. That seemed cumbersome.

In retrospect, that was the wrong decision. We've had to jump through
hoops to translate types between the inferable and non-inferable
variants, which has been quite brittle. Combined with the original point
above, that much of the assignability logic will become more identical
between inferable and non-inferable, there is less justification for the
two `Type` variants. And plumbing an extra `inferable` parameter through
all of these methods turns out to not be as bad as I anticipated.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-10-16 15:59:46 -04:00
Ibraheem Ahmed 25023cc0ea
[ty] Use declared variable types as bidirectional type context (#20796)
## Summary

Use the declared type of variables as type context for the RHS of assignment expressions, e.g.,
```py
x: list[int | str]
x = [1]
reveal_type(x)  # revealed: list[int | str]
```
2025-10-16 15:40:39 -04:00
Ibraheem Ahmed 1ade4f2081
[ty] Avoid unnecessarily widening generic specializations (#20875)
## Summary

Ignore the type context when specializing a generic call if it leads to
an unnecessarily wide return type. For example, [the example mentioned
here](https://github.com/astral-sh/ruff/pull/20796#issuecomment-3403319536)
works as expected after this change:
```py
def id[T](x: T) -> T:
    return x

def _(i: int):
    x: int | None = id(i)
    y: int | None = i
    reveal_type(x)  # revealed: int
    reveal_type(y)  # revealed: int
```

I also added extended our usage of `filter_disjoint_elements` to tuple
and typed-dict inference, which resolves
https://github.com/astral-sh/ty/issues/1266.
2025-10-16 19:17:37 +00:00