Summary
Consider the following snippet:
from ty_extensions import Intersection
from typing import Self, reveal_type
class Bar:
def method(self) -> Self:
return self
class Foo: ...
def f(x: Intersection[Bar, Foo]):
reveal_type(x.method())
Currently we reveal Bar on the last line, but I think we should reveal Bar & Foo instead. Methods that are annotated as returning Self at runtime almost always have bodies with return self inside them -- and self in this context must be an instance of both Foo and Bar.
This starts to cause false positives on codebases such as psycopg if we merge astral-sh/ruff#24761, due to snippets like this in psycopg:
from typing import NamedTuple, Any, Sequence, Protocol
class RowMaker[Row: tuple[Any, ...]](Protocol):
def __call__(self, values: Sequence[Any], /) -> Row: ...
def namedtuple_row(namedtuple_cls: type[NamedTuple]) -> RowMaker[NamedTuple]:
# error[invalid-return-type] Return type does not match returned value: expected `RowMaker[tuple[object, ...] & NamedTupleLike]`, found `bound method type[NamedTupleLike]._make(iterable: Iterable[Any]) -> NamedTupleLike`
return namedtuple_cls._make
Version
No response
Summary
Consider the following snippet:
Currently we reveal
Baron the last line, but I think we should revealBar & Fooinstead. Methods that are annotated as returningSelfat runtime almost always have bodies withreturn selfinside them -- andselfin this context must be an instance of bothFooandBar.This starts to cause false positives on codebases such as psycopg if we merge astral-sh/ruff#24761, due to snippets like this in psycopg:
Version
No response