[ty] Don't confuse multiple occurrences of typing.Self when binding bound methods by dcreager · Pull Request #21754 · astral-sh/ruff (original) (raw)

added 2 commits

December 2, 2025 10:48

@dcreager

@dcreager

@dcreager dcreager added the ty

Multi-file analysis & type inference

label

Dec 2, 2025

@dcreager

ibraheemdev

dcreager added a commit that referenced this pull request

Dec 2, 2025

@dcreager

AlexWaygood pushed a commit that referenced this pull request

Dec 2, 2025

@dcreager @AlexWaygood

… bound methods (#21754)

In the following example, there are two occurrences of typing.Self, one for Foo.foo and one for Bar.bar:

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 Selfs, 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 astral-sh/ty#1713

dcreager added a commit that referenced this pull request

Dec 3, 2025

@dcreager

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters

[ Show hidden characters]({{ revealButtonHref }})