15139 Commits

Author SHA1 Message Date
renovate[bot] 41eab24de5 Update uraimo/run-on-arch-action action to v3.1.0 (#25011)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-06 06:05:50 +01:00
renovate[bot] 5b74d31928 Update dependency astral-sh/uv to v0.11.10 (#25002)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-06 06:05:09 +01:00
renovate[bot] 532e4ae649 Update prek dependencies (#25003)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-06 06:00:21 +01:00
renovate[bot] 885d50ead2 Update taiki-e/install-action action to v2.75.25 (#25007)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-06 05:57:00 +01:00
renovate[bot] 44b51162fe Update Rust crate mimalloc to v0.1.50 (#25006)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-06 05:55:59 +01:00
renovate[bot] 02c70adf49 Update Rust crate libc to v0.2.186 (#25005)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-06 05:55:29 +01:00
renovate[bot] 496ef2a7a6 Update maturin to v1.13.1 (#25009)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-06 05:54:38 +01:00
renovate[bot] 94aa770359 Update CodSpeedHQ/action action to v4.15.0 (#25008)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-06 05:51:44 +01:00
renovate[bot] c58ec5a83e Update Rust crate jiff to v0.2.24 (#25004)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-06 05:50:54 +01:00
Erik Johnson ea6be89b0a Increase max value of line-length setting (#24962)
Co-authored-by: Erik Johnson <source@ekriirke.net>
Co-authored-by: Micha Reiser <micha@reiser.io>
2026-05-05 14:08:51 +00:00
Lérè 2558b41d61 [ty] Fix the Pyodide assets deployment in the ty playground. (#24994)
<!--
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?
- Does this PR follow our AI policy
(https://github.com/astral-sh/.github/blob/main/AI_POLICY.md)?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->
- Adds some graceful degradation to Pyodide loading failures in the ty
playground (with the result that the entire playground UI doesn't
disappear if we only fail to execute a code run).
- Corrects the placement of assets in our playground deployment, and
adds some validation to the deployment workflow as a simple regression
test

Closes https://github.com/astral-sh/ty/issues/3409.

## Test Plan

I've verified the new asset layout in a local build of the playground. I
think that's sufficient, but I will monitor the production playground
deployment and revert this change if necessary.

<!-- How was it tested? -->
2026-05-04 19:20:09 -07:00
Lérè a8d3850605 [ty] Selectively promote a union of homogeneous fixed-length tuples to a single variadic tuple. (#24705)
<!--
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?
- Does this PR follow our AI policy
(https://github.com/astral-sh/.github/blob/main/AI_POLICY.md)?
-->

## Summary

This implements structural promotion of tuple size in the inferred type
of a collection literal.

The promotion only applies to a very specific circumstance: when tuple
literals in an inferred collection element type produce a union of
homogeneous fixed-length tuples of differing lengths, and only literal
tuple sources have contributed to that type, then we widen that union to
a single variadic tuple (e.g., `tuple[str] | tuple[str, str]` is widened
to `tuple[str, ...]`).

The result is that this scenario described in
https://github.com/astral-sh/ty/issues/2620 succeeds:

```python
languages = {
    "python": (".py", ".pyi"),
    "javascript": (".js", ".jsx", ".ts", ".tsx"),
}

# This no longer errors after this change, because the type of languages is `dict[str, tuple[str, ...]` rather than `dict[str, tuple[str, str]] | tuple[str, str, str, str]]`
languages["ruby"] = (".rb",) 
```

Closes https://github.com/astral-sh/ty/issues/2620.

### Approach

- I created a new submodule that encapsulates the tuple size promotion
policy. It exposes a `TupleSizePromotionConstraints` struct that we use
during inference to record the scenarios in which we should **not**
attempt to promote a tuple. If no such disqualifying scenarios are
encountered, then tuple size promotion is attempted. The set of
disqualifying scenarios is documented in new mdtests.
- I think the policy for when to promote unions that involve empty
tuples deserves particular scrutiny. Since empty tuples do not have an
element type, they present a special case. The rule I've chosen is that
empty tuples do not contribute to evidence of different tuple lengths.
That means that a union containing an empty tuple must also contain
other tuples of differing lengths to trigger promotion (i.e., `[(),
(1,)]` remains `list[tuple[()] | tuple[int]]`, but `[(), (1,), (1,2)]`
is promoted to `list[tuple[int, ...]]`. This is conservative and, I
hope, useful for modeling situations in which the size of a tuple is
specifically meant to be 0 or N.

## Test Plan

Please see new and updated mdtests.

<!-- How was it tested? -->
2026-05-04 11:31:21 -07:00
Charlie Marsh a88b2f619c [ty] Cache results in desperate module resolution (#24977)
## Summary

Per Codex, in pyx, this adds 1.3MB to the cache (0.4%) in return for a
5-10% faster walltime.
2026-05-04 06:54:41 -07:00
Shunsuke Shibayama b409cbeea6 [ty] implement proper handling of recursive types in CycleDetector (#24773)
## Summary

This fixes the known issues with handling recursive aliases, as
described
[here](https://github.com/astral-sh/ty/issues/3195#issuecomment-4184926298)
and elsewhere.

```py
from typing import reveal_type

type A = list[A]

def foo(x: A):
    reveal_type(x[0])  # main: list[Any] -> this PR: list[A]
```

This allows us to safely remove the `MAX_RECURSION_DEPTH` limit that was
associated with `CycleDetector`.

The point is that in the previous implementation, we simply compared
types using hash values ​​to guard against recursion, but this was
insufficient. By manually adding equality checks, the depth limit is no
longer necessary.

Stacked on https://github.com/astral-sh/ruff/pull/24803

## Test Plan

mdtest updated

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2026-05-02 21:26:11 -04:00
Charlie Marsh e002c44494 [ty] Skip parameter accumulation for object variadics (#24976) 2026-05-02 20:41:55 -04:00
Shahar Naveh 5ee1d0cd51 Add missing rust related files when detecting changes in CI (#24971) 2026-05-02 13:43:43 +02:00
Charlie Marsh 5f040fab4b [ty] Expand support for narrowing within walruses (#24968)
## Summary

Support narrowing for a few more already-supported sites, but in the
context of a walrus, as in:

```python
def f(t: tuple[int, int] | tuple[None, None]):
    if (first := t[0]) is not None:
        reveal_type(first)  # int
        reveal_type(t)      # tuple[int, int]
    else:
        reveal_type(first)  # None
        reveal_type(t)      # tuple[None, None]
```
2026-05-01 23:09:36 -04:00
Charlie Marsh b1fe4e405d [ty] Fix missing visitor guard in Callable branch (#24964)
## Summary

This came up in a subsequent PR, but I think it's just missing here.
2026-05-01 17:06:23 -04:00
Charlie Marsh e990dfd069 [ty] Allow reference finding in stringified annotations (#24956)
## Summary

Stringified annotations were being guarded by the `includeDeclaration`
flag, so `MyClass` inside `"MyClass"` wasn't being treated as a
reference, which seems unintentional.

Closes https://github.com/astral-sh/ty/issues/3386.
2026-05-01 12:35:11 -04:00
Charlie Marsh 81c81f6892 [ty] Unpack Union of TypedDict in various sites (#24958)
## Summary

We already have a helper for this; we just weren't using it everywhere.
2026-05-01 12:18:58 -04:00
Shunsuke Shibayama c6057e034b [ty] Fix unbounded type growth in nested-typevar substitutions (#24803) 2026-05-01 15:01:14 +09:00
github-actions[bot] 9e2dd4ab4d [ty] Sync vendored typeshed stubs (#24952)
Close and reopen this PR to trigger CI

---------

Co-authored-by: typeshedbot <>
2026-04-30 22:16:10 -04:00
Charlie Marsh b3fb864847 [ty] Show a diagnostic for unsupported inferred Python version (#24581)
## Summary

This PR adds the infrastructure to surface diagnostics during project
and program settings resolution. The motivating use-case is: when we see
an unsupported Python version in an editor, we want to surface a
diagnostic rather than limiting to a `tracing` warning, as in:

```
warning[unsupported-python-version]: Ignoring unsupported inferred Python version `3.16`; ty will use Python 3.14 instead.
 --> venv/pyvenv.cfg:2:16
  |
2 | version_info = 3.16.0
  |                ^^^^^^
3 | home = base/bin
  |
info: Expected one of `3.7`, `3.8`, `3.9`, `3.10`, `3.11`, `3.12`, `3.13`, `3.14`, `3.15`.
info: Set `python-version` explicitly to override the inferred version.
info: The version was inferred from your virtual environment metadata.
```
2026-04-30 15:08:38 -04:00
Charlie Marsh 95670c1f56 [ty] Model functools.partial call results (#24582)
## Summary

This PR adds initial support for `functools.partial`, including:

- Constructor-time checking of bound arguments (e.g., `partial(f, "x")`
should report an immediate error if `"x` is not a valid type for the
parameter)
- Reduced signatures for partials (e.g., `def f(a: int, b: str, *, c:
bool) -> bytes` with `partial(f, 1)` becomes `partial[(b: str, *, c:
bool) -> bytes]`).
- Support for overloads, assignability checks, and more.

There are a few things that are _not_ covered and were instead cordoned
off into separate commits, namely:

- Preserving unprovided generic type variables in the returned partial
signature (fixed in: https://github.com/astral-sh/ruff/pull/24583). As
of this commit, we get:

```python
from functools import partial
from typing import TypeVar

T = TypeVar("T")
U = TypeVar("U")

def combine(a: T, b: U) -> tuple[T, U]:
    return (a, b)

# partial[(b: Unknown) -> tuple[Literal[1], Unknown]]
p = partial(combine, 1)
```

- Keyword overrides in generics (e.g., `partial(combine, b=1)` can later
be called as `p("x", b="y")`, since keyword arguments can be overridden
at call time -- TIL!).
- Constructor modeling (`__new__`, etc.)

But this gets us much of the way there. After this PR, I believe our
handling of `functools.partial` is generally ahead of Mypy and Pyright
with the significant exception of generic modeling, where ty is behind.

(I choose to include tests for the above in
`crates/ty_python_semantic/resources/mdtest/call/functools_partial.md`,
with TODOs, which get resolved in subsequent PRs.)

See: https://github.com/astral-sh/ty/issues/1536.
2026-04-30 11:28:06 -04:00
Micha Reiser 0fb4f62330 Add maturin, MSRV, Rust toolchain to renovate config (#24941) 2026-04-30 16:04:18 +02:00
Charlie Marsh 7eb38d121c [ty] Avoid expression_type calls for syntax error targets in unpacking assignment (#24663)
## Summary

We parse `something, not = (1, 2)` as (on the LHS) a name target
(`something`) and a unary target (`not`) followed by an empty name. As a
result, we never visit the `not` or its name, which means we never infer
or record a type for that malformed subtree in `UnpackResult`.

Later, an `expression_type(...)` lookup for any subexpression can miss
and panic.

Closes https://github.com/astral-sh/ty/issues/3283.
2026-04-30 09:29:33 -04:00
Charlie Marsh 81057044f4 [ty] Guard recursive protocol signature comparisons (#24665)
## Summary

This PR adds a recursion guard for signature comparisons (keyed by
(source definition, target definition, relation)), used to prevent a
stack overflow in structural protocol matching. Previously, recursive
protocols would just recurse with a new specialization; now, we assume
success when we see the same pair in a single check, and continue from
there.

Closes https://github.com/astral-sh/ty/issues/3208.
2026-04-30 12:45:01 +00:00
Denys Zhak fba03a6b47 Fix F811 false positive for class methods (#24933) 2026-04-30 13:33:56 +02:00
Eyüp Can Akman f32733c063 [flake8-pyi] Fix PYI016 false positive for f-string debug specifier (#24098)
Co-authored-by: Micha Reiser <micha@reiser.io>
2026-04-30 11:14:25 +02:00
Tobias Hernstig bbc529bc8a docs: Use correct number of lint rules supported (#24942) 2026-04-30 09:08:53 +00:00
Charlie Marsh 97cf85d454 [ty] Fix TypeIs assignability with gradual types (#24928)
## Summary

Prior to this change, for `TypeIs`, we only stored the
`T.top_materialization()` of the type. So for assignability, we checked
against the materialized narrowing type, rather than the user-declared
type. The two are conflated.

I think this causes problems for cases like:

```python
static_assert(is_assignable_to(TypeIs[Sequence[int]], TypeIs[Sequence[Any]]))
static_assert(not is_assignable_to(TypeIs[Sequence[int]], TypeIs[Sequence[object]]))
```

On `main`, the first assertion fails.
2026-04-29 17:08:21 -04:00
Charlie Marsh 35228e5a84 [ty] Respect commented-out lines in the conformance test suite (#24932)
## Summary

We were treating this line from the conformance tests as a false
negative:


https://github.com/python/typing/blob/5a701a037b5243df1f39622b642893d865f06205/conformance/tests/generics_syntax_infer_variance.py#L72
2026-04-29 12:56:26 -04:00
Charlie Marsh e6528502ba [ty] Support infer_variance for legacy TypeVar (#24930)
## Summary

See:
https://github.com/astral-sh/ruff/pull/24927#discussion_r3162016951.
2026-04-29 12:49:34 -04:00
Matthew Mckee 1a794b966a Add hover support for pep 695 type alias (#24926) 2026-04-29 16:23:49 +00:00
Lérè e97bab008e [ty] Prevent quoted annotation tokens from leaking across notebook cells. (#24919)
<!--
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?
- Does this PR follow our AI policy
(https://github.com/astral-sh/.github/blob/main/AI_POLICY.md)?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

This prevents semantic tokens from a quoted type annotation from leaking
across notebook cells. Previously, such a leak would cause wonky syntax
highlighting as described in
https://github.com/astral-sh/ty/issues/3307.

The root cause of the issue was accidental omission of a cell's source
range from the filter used to determine the bounds of the semantic token
request.

Closes https://github.com/astral-sh/ty/issues/3307.

## Test Plan

Please see added regression test.
<!-- How was it tested? -->

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2026-04-29 16:17:06 +00:00
Charlie Marsh 3cec7f2315 [ty] Support variance keywords in ParamSpec (#24927)
## Summary

This PR adds `covariant`, `contravariant`, and `infer_variance` support
to `ParamSpec`.

See: https://github.com/python/typing/pull/2215.

See:
https://github.com/astral-sh/ruff/pull/24479#pullrequestreview-4192292282.
2026-04-29 11:30:39 -04:00
Anders Brams bfe5b51890 [ty] Offer string literal completion suggestions based on expected type (#24555)
Co-authored-by: Micha Reiser <micha@reiser.io>
2026-04-29 17:16:58 +02:00
Charlie Marsh ea4b40641a Restrict PYI034 for in-place operations to enclosing class (#24511)
## Summary

In `.py` and `.pyi` files, we now only flag cases in which the return
type is the enclosing class, like:

```python
class A:
    def __iadd__(self) -> A:
        return self
```

As opposed to:

```python
class A:
    def __iadd__(self) -> int:
        return self
```

Closes https://github.com/astral-sh/ruff/issues/24462.
2026-04-29 10:16:00 -04:00
Charlie Marsh 1b931ba658 [ty] Fix ParamSpec defaults and alias variance (#24479)
## Summary

This PR fixes several ParamSpec variance and gradual-specialization edge
cases that fell out of https://github.com/astral-sh/ruff/pull/24319.

We also now treat `typing_extensions.ParamSpec` defaults like
`typing.ParamSpec` defaults, which I think was an oversight.
2026-04-29 09:04:45 -04:00
Micha Reiser 038cf9e9ef Simplify the playground's markdown template (#24924) 2026-04-29 11:47:29 +02:00
Micha Reiser 8366b2839d Update renovate configuration (#24922) 2026-04-29 09:51:59 +02:00
Micha Reiser 3433660c96 Update Renovate configuration (#24874) 2026-04-29 08:58:45 +02:00
David Peter cf14481f44 Semantic syntax errors: better error message for global vs parameter (#24902)
## Summary

This is an attempt to improve the error message for something like
```py
a = 1

def f(a):
    global a
```

I realize that the previous wording ("name 'a' is parameter and global")
is used by CPython itself, but unless we are trying to be consistent
with CPython, I think we can improve upon this? The previous version
seemed a bit cryptic to me when I first saw it.

## Test Plan

Updated snapshot tests
2026-04-29 08:46:57 +02:00
David Peter 524158dbd0 [ty] Add missing error context node for protocol to protocol assignability (#24905)
## Summary

Thank you for spotting this, @carljm.

## Test Plan

New Markdown tests
2026-04-29 08:46:09 +02:00
Alex Waygood cd325995fc [ty] Increase the number of ecosystem-analyzer shards to 4 (#24893) 2026-04-28 17:55:32 -04:00
Charlie Marsh 1ccaf7c9e5 [ty] Store call argument data together (#24851)
## Summary

These values are typically accessed together (e.g.,
`ArgumentMatcher::new`), and the construction now halves the number of
vector allocations.
2026-04-28 14:01:37 -04:00
Micha Reiser 2205ab0192 [ty] Fix playground build (#24907) 2026-04-28 19:02:37 +02:00
Micha Reiser de812e7efb [ty] Show nice can't rename message for symbols that can't be renamed in playground (#24906) 2026-04-28 16:29:38 +00:00
Charlie Marsh 0ea258f0da [ty] Lazily build TypeVar accumulations (#24782)
## Summary

Given a generic specialization, we were rebuilding the constraints after
every argument, rather than all-at-once.

E.g., for:

```python
def combine[T](a: T, b: T, c: T, d: T) -> T:
    return a

combine(("name", 1), ("id", 2), ("flag", True), ("size", 4))
```

Each argument constrains the same type variable `T`:

```python
T = tuple[Literal["name"], Literal[1]]
T = tuple[Literal["id"], Literal[2]]
T = tuple[Literal["flag"], Literal[True]]
T = tuple[Literal["size"], Literal[4]]
```

On main, we then compute (roughly):
```
T = A
T = union(A, B)
T = union(union(A, B), C)
T = union(union(A, B, C), D)
```

Now, we create a builder and construct at the end. This has a
significant impact on functions with many arguments, but also reduces
memory on real-world projects, which is great.
2026-04-28 12:22:33 -04:00
Charlie Marsh 975e029640 [ty] Add a benchmark for TypeVar accumulation (#24781)
## Summary

Adds a microbenchmark to assess
https://github.com/astral-sh/ruff/pull/24782.
2026-04-28 11:56:55 -04:00