ruff/crates/ty_python_semantic
Douglas Creager 33b942c7ad
[ty] Handle annotated `self` parameter in constructor of non-invariant generic classes (#21325)
This manifested as an error when inferring the type of a PEP-695 generic
class via its constructor parameters:

```py
class D[T, U]:
    @overload
    def __init__(self: "D[str, U]", u: U) -> None: ...
    @overload
    def __init__(self, t: T, u: U) -> None: ...
    def __init__(self, *args) -> None: ...

# revealed: D[Unknown, str]
# SHOULD BE: D[str, str]
reveal_type(D("string"))
```

This manifested because `D` is inferred to be bivariant in both `T` and
`U`. We weren't seeing this in the equivalent example for legacy
typevars, since those default to invariant. (This issue also showed up
for _covariant_ typevars, so this issue was not limited to bivariance.)

The underlying cause was because of a heuristic that we have in our
current constraint solver, which attempts to handle situations like
this:

```py
def f[T](t: T | None): ...
f(None)
```

Here, the `None` argument matches the non-typevar union element, so this
argument should not add any constraints on what `T` can specialize to.
Our previous heuristic would check for this by seeing if the argument
type is a subtype of the parameter annotation as a whole — even if it
isn't a union! That would cause us to erroneously ignore the `self`
parameter in our constructor call, since bivariant classes are
equivalent to each other, regardless of their specializations.

The quick fix is to move this heuristic "down a level", so that we only
apply it when the parameter annotation is a union. This heuristic should
go away completely 🤞 with the new constraint solver.
2025-11-10 19:46:49 -05:00
..
resources [ty] Handle annotated `self` parameter in constructor of non-invariant generic classes (#21325) 2025-11-10 19:46:49 -05:00
src [ty] Handle annotated `self` parameter in constructor of non-invariant generic classes (#21325) 2025-11-10 19:46:49 -05:00
tests [ty] Limit shown import paths to at most 5 unless ty runs with `-v` (#20912) 2025-10-16 13:18:09 +02:00
Cargo.toml [ty] Some more simplifications when rendering constraint sets (#21009) 2025-10-22 13:38:44 -04:00
build.rs Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
mdtest.py [ty] Set `INSTA_FORCE_PASS` and `INSTA_OUTPUT` environment variables from mdtest.py (#21029) 2025-10-22 15:32:14 +01:00
mdtest.py.lock Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00