ruff/crates/ty_python_semantic/resources/mdtest/annotations
Douglas Creager 508c0a0861
[ty] Don't confuse multiple occurrences of `typing.Self` when binding bound methods (#21754)
In the following example, there are two occurrences of `typing.Self`,
one for `Foo.foo` and one for `Bar.bar`:

```py
from typing import Self, reveal_type

class Foo[T]:
    def foo(self: Self) -> T:
        raise NotImplementedError

class Bar:
    def bar(self: Self, x: Foo[Self]):
        # SHOULD BE: bound method Foo[Self@bar].foo() -> Self@bar
        # revealed: bound method Foo[Self@bar].foo() -> Foo[Self@bar]
        reveal_type(x.foo)

def f[U: Bar](x: Foo[U]):
    # revealed: bound method Foo[U@f].foo() -> U@f
    reveal_type(x.foo)
```

When accessing a bound method, we replace any occurrences of `Self` with
the bound `self` type.

We were doing this correctly for the second reveal. We would first apply
the specialization, getting `(self: Self@foo) -> U@F` as the signature
of `x.foo`. We would then bind the `self` parameter, substituting
`Self@foo` with `Foo[U@F]` as part of that. The return type was already
specialized to `U@F`, so that substitution had no further affect on the
type that we revealed.

In the first reveal, we would follow the same process, but we confused
the two occurrences of `Self`. We would first apply the specialization,
getting `(self: Self@foo) -> Self@bar` as the method signature. We would
then try to bind the `self` parameter, substituting `Self@foo` with
`Foo[Self@bar]`. However, because we didn't distinguish the two separate
`Self`s, and applied the substitution to the return type as well as to
the `self` parameter.

The fix is to track which particular `Self` we're trying to substitute
when applying the type mapping.

Fixes https://github.com/astral-sh/ty/issues/1713
2025-12-02 13:15:09 -05:00
..
annotated.md [ty] Support stringified annotations in value-position `Annotated` instances (#21447) 2025-11-14 13:09:09 +00:00
any.md [ty] Use "cannot" consistently over "can not" (#21255) 2025-11-03 10:38:20 -05:00
callable.md [ty] Understand legacy and PEP 695 `ParamSpec` (#21139) 2025-11-06 11:14:40 -05:00
deferred.md [ty] fix global symbol lookup from eager scopes (#21317) 2025-11-12 10:15:51 -08:00
generic_alias.md [ty] Remove `GenericAlias`-related todo type (#21728) 2025-12-01 13:02:38 +00:00
int_float_complex.md [ty] Improve disjointness inference for `NominalInstanceType`s and `SubclassOfType`s (#18864) 2025-06-24 20:27:37 +00:00
invalid.md [ty] tighten up handling of subscripts in type expressions (#21503) 2025-11-18 10:43:07 -08:00
literal.md [ty] tighten up handling of subscripts in type expressions (#21503) 2025-11-18 10:43:07 -08:00
literal_string.md [ty] Improve several "Did you mean?" suggestions (#21597) 2025-11-25 10:29:01 +00:00
never.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
new_types.md [ty] Remove `GenericAlias`-related todo type (#21728) 2025-12-01 13:02:38 +00:00
optional.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
self.md [ty] Don't confuse multiple occurrences of `typing.Self` when binding bound methods (#21754) 2025-12-02 13:15:09 -05:00
starred.md [ty] Return `Option<TupleType>` from `infer_tuple_type_expression` (#19735) 2025-08-04 13:48:19 +01:00
stdlib_typing_aliases.md [ty] Fix bug where ty would think all types had an `__mro__` attribute (#20995) 2025-10-27 11:19:12 +00:00
string.md [ty] Emit error for invalid binary operations in type expressions (#18991) 2025-06-30 10:06:01 +02:00
union.md [ty] Implicit type aliases: Support for PEP 604 unions (#21195) 2025-11-03 21:50:25 +01:00
unsupported_special_forms.md [ty] support PEP 613 type aliases (#21394) 2025-11-20 17:59:35 -08:00
unsupported_special_types.md Generalize special-casing for enums constructed with the functional syntax (#17885) 2025-05-06 11:02:55 +01:00
unsupported_type_qualifiers.md [ty] validate constructor call of `TypedDict` (#19810) 2025-08-25 14:45:52 +02:00