Assigning to intermediate variable changes type checking results
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Python
- Sterne
- 20.6k
- Forks
- 3.3k
- PR-Merge-Kennzahlen
- PR-Kennzahlen ausstehend
Beschreibung
Bug Report
- Assigning to an intermediate variable can change inference results.
- Incorrect inference when inside a function call.
# mypy: disable-error-code=empty-body
# fmt: off
from typing import Iterable, Iterator
class Vec[T]: # proxy for list[T]
def getitem(self, i: int) -> T: ... # ensure invariance of T
def setitem(self, i: int, v: T) -> None: ... # ensure invariance of T
def __init__(self, iterable: Iterable[T], /) -> None: ...
def __iter__(self) -> Iterator[T]: ...
def __add__[S](self, value: "Vec[S]", /) -> "Vec[S | T]": ...
def fmt(arg: Iterable[int | str]) -> None: ... # <-- union plays a role
l1: Vec[int] = Vec([1])
l2: Vec[int] = Vec([1])
fmt(l1 + l2) # ❌ Unsupported operand types for + ("Vec[int]" and "Vec[int]")
dummy = l1 + l2
fmt(dummy) # ✅
Same example without PEP 695
https://mypy-play.net/?mypy=latest&python=3.12&gist=43a91e52a767ac27f2706795d45bdef1
# mypy: disable-error-code=empty-body
# fmt: off
from typing import TypeVar, Generic, Iterable, Iterator
T = TypeVar("T")
S = TypeVar("S")
class Vec(Generic[T]):
def getitem(self, i: int) -> T: ... # ensure invariance of T
def setitem(self, i: int, v: T) -> None: ... # ensure invariance of T
def __init__(self, iterable: Iterable[T], /) -> None: ...
def __iter__(self) -> Iterator[T]: ...
def __add__(self, value: "Vec[S]", /) -> "Vec[S | T]": ...
def fmt(arg: Iterable[int | str]) -> None: ...
l1: Vec[int] = Vec([1])
l2: Vec[int] = Vec([1])
fmt(l1 + l2) # ❌ Unsupported operand types for + ("Vec[int]" and "Vec[int]")
dummy = l1 + l2
fmt(dummy) # ✅
original bug report
Bug Report
I was testing this PR (https://github.com/python/typeshed/issues/14283) for typeshed that simplifies list.__add__ from
@overload
def __add__(self, value: list[_T], /) -> list[_T]: ...
@overload
def __add__(self, value: list[_S], /) -> list[_S | _T]: ...
to
def __add__(self, value: list[_S], /) -> list[_S | _T]: ...
This seems to work generally, but there are some weird circumstances when it bugs out. It seems most of them appear when a concatenation is given as an argument to another function.
As an example, this is one of the lines that gets flagged:
https://github.com/python/mypy/blob/5081c59b9c0c7ebe7070c62a4aeaf3d0de203a24/mypyc/crash.py#L29
However, mypy stops complaing if it is changed to
dummy = tb + tb2
for s in traceback.format_list(dummy):
Assigning to an intermediate variable changed the type checking results (!)
I couldn't reproduce this behavior using a custom class, which makes me believe this is probably due to some weird special casing for builtins.
To Reproduce
git clone --branch polymorphic_overload_test https://github.com/randolf-scholz/typeshed.git
git clone https://github.com/python/mypy.git
cd typeshed
uv venv --seed
source .venv/bin/activate
uv pip install -r requirements-tests.txt
mkdir tmp
cp ../mypy/mypyc/crash.py tmp/tmp.py
python -m mypy.stubtest --custom-typeshed-dir=../typeshed tmp
Expected Behavior
Assigning to an intermediate variable shouldn't affect type inference.
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne mit den Beispielen im Issue und reproduziere das Verhalten anhand der bereitgestellten mypy-playground-Links. Führe dann den aufgeführten stubtest-Befehl mit mypyc/crash.py aus und vergleiche den direkten Funktionsaufruf mit der Version mit einer Zwischenvariable. Erledigt ist es, wenn das Zuweisen des Zwischenergebnisses das Ergebnis der Typprüfung nicht mehr verändert.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- compilers
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Ruhig
- Klarheit
- Größtenteils klar
- Anfängerfreundlichkeit
- 48/100