python / python/mypy

Union of `Never` can't be used

Aperta
#18,779 3 commenti 1 reazione 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

bug topic-union-types
Lingua principale
Python
Stelle
20.6k
Fork
3.3k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

Bug Report

Functions which optionally take a value of Never type have impossible requirements placed on usages of that optional value.

To Reproduce

https://gist.github.com/mypy-play/a49d72bdacc179ffda5f69d8b66f41ff

from typing import Never


def blah(s: Never | str) -> None:
    print(s + "hi")

Expected Behavior

The code type-checks. Since it is impossible for any variable to take a value of type Never, the type signature of blah is equivalent to str -> None. The function's body is valid when s is annotated with type str, so it should be valid when annotated with Never | str.

Actual Behavior

main.py:5: error: Unsupported left operand type for + ("Never")  [operator]
main.py:5: note: Left operand is of type "Never | str"
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Python 3.12
  • MyPy 1.15.0, invocation as performed in the Playground

Background

Pyright appears to do the right thing here: it accepts this code.

I ran into this when implementing this pattern, which is me placing types around something I found untyped in the wild:

T = TypeVar("T", contravariant=True)
class _MyProtocol(Protocol[T]):
  def _foo(self, arg: T | IO[str]) -> None: ...

try:
    import foo
    class _MyImpl(_MyProtocol[foo.Foo]):
      def _foo(self, arg: foo.Foo | IO[str]) -> None: 
        # do something here
        pass

    MyType = _MyImpl

except ImportError:
    class _MyImplNone(_MyProtocol[Never]):
      def _foo(self, arg: Never | IO[str]) -> None:
        # correctly assume arg is an IO[str] here
        pass

    MyType = _MyImplNone

That way, MyType has type _MyProtocol[foo.Foo] | _MyProtocol[Never], allowing a type-level discrimination of whether the foo functionality is present or not.

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 riproduttore minimo in Python nell’issue o nell’esempio mypy-play collegato e confronta l’errore dell’operatore riportato con il comportamento previsto equivalente a str. Traccia come vengono gestite durante il controllo dei tipi le unioni contenenti Never, quindi aggiungi la copertura per la funzione mostrata e conferma che mypy la accetti senza l’errore dell’operando Never.

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

Valutazione

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

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.