python / python/mypy

Incorrect type inference with PEP 646 Unpack and self-type annotations

Aperta
#20,651 11 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

bug topic-pep-646 topic-type-variables
Lingua principale
Python
Stelle
20.6k
Fork
3.3k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

Bug Report

When a generic class uses TypeVarTuple (PEP 646) and a method has a self-type annotation that "reshapes" the type parameters, mypy incorrectly infers the return type when the class is instantiated with Unpack[Tuple[Any, ...]].

Specifically, mypy infers the return type as None instead of Any | None, leading to false "unreachable code" errors.

To Reproduce

from typing import Generic, TypeVar, Optional, Iterator, Any, Tuple
from typing_extensions import TypeVarTuple, Unpack

_T = TypeVar("_T", bound=Any)
_Ts = TypeVarTuple("_Ts")


class Result(Generic[Unpack[_Ts]]):
    """Generic result class that takes variadic type parameters.

    This mimics SQLAlchemy's Result class which is generic over Unpack[_Ts].
    """

    def scalar(self: "Result[_T, Unpack[Tuple[Any, ...]]]") -> Optional[_T]:
        return None




def test_function() -> Iterator[Any]:
    result: Result[Unpack[Tuple[Any, ...]]] = Result()
    reveal_type(result)
    data = result.scalar()
    reveal_type(data)
    if data is None:
        return
    yield from iter(data)

Expected Behavior

If we run pyright, the type of "data" is "Any | None" and the yield from is reachable:

$ pyright mypy_bug_repro.py 
/home/classic/dev/sqlalchemy/mypy_bug_repro.py
  /home/classic/dev/sqlalchemy/mypy_bug_repro.py:22:17 - information: Type of "result" is "Result[*tuple[Any, ...]]"
  /home/classic/dev/sqlalchemy/mypy_bug_repro.py:24:17 - information: Type of "data" is "Any | None"
0 errors, 0 warnings, 2 informations

Actual Behavior

Mypy sees "data" as None in all cases

$ mypy --warn-unreachable mypy_bug_repro.py 
mypy_bug_repro.py:22: note: Revealed type is "mypy_bug_repro.Result[Unpack[builtins.tuple[Any, ...]]]"
mypy_bug_repro.py:24: note: Revealed type is "None"
mypy_bug_repro.py:27: error: Statement is unreachable  [unreachable]
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version: mypy 1.19.1 (compiled: yes)
  • Python version: 3.14
  • typing_extensions version: latest (for TypeVarTuple, Unpack)
  • Pyright version (for comparison): 1.1.408

notes

So I used Claude to refactor SQLAlchemy's structures into standalone features. Additional commentary from Claude which may or may not be helpful:

The bug appears to be in mypy's type parameter matching logic. When trying to match:

  • Instance type: Result[Unpack[Tuple[Any, ...]]]
  • Against self-type: Result[_T, Unpack[Tuple[Any, ...]]]

Mypy should extract _T = Any from the first element of the unpacked tuple, but instead appears to fail at this extraction, possibly binding _T to Never or treating it as non-existent, resulting in Optional[Never] = None.

downstream SQLAlchemy issues is at https://github.com/sqlalchemy/sqlalchemy/discussions/13089 which is local to the new 2.1.0beta1 release that uses pep-646

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia con il reproducer autonomo descritto nell’issue ed eseguilo con mypy --warn-unreachable per confermare il tipo rivelato e l’errore di codice irraggiungibile. Traccia la corrispondenza dei parametri di tipo di mypy per Result[Unpack[Tuple[Any, ...]]] rispetto all’annotazione del tipo self; il lavoro è completo quando scalar() viene inferito come Any | None e il percorso yield non viene più segnalato come irraggiungibile.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
compilers
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.