python / python/mypy

Mypy emits two conflicting results for reveal_type

Aperta
#10,739 4 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

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

Descrizione

Bug Report

My colleague @ahuhn and I encountered a situation where mypy emits two different outputs for one reveal_type call:

from decimal import Decimal
from typing import Union

def f(elem: Union[int, str, Decimal]) -> None:
    if isinstance(elem, int):
        return

    for _ in range(3):
        if isinstance(elem, (Decimal, int)) and elem > 10:
            continue
        reveal_type(elem)

    return None

Running mypy emits two lines for the reveal_type call, one correct and the other incorrect. In the incorrect reveal statement, the type narrowing at the top of the function is lost:

$ mypy example.py
example.py:11: note: Revealed type is "Union[builtins.str, decimal.Decimal]"   # expected
example.py:11: note: Revealed type is "Union[builtins.int, builtins.str, decimal.Decimal]"   # wrong

Expected Behavior
Expected only one piece of output for one reveal_type, and for that output to maintain the type narrowing from the top of the function.

Your Environment

We encountered this on mypy 0.812, but it also repros on latest master (currently 416f57b) using python 3.8.6.

A variation of interest: if you add a line of code after the reveal_type, then the second reveal_type output broadens to include Any:

from decimal import Decimal
from typing import Union

def f(elem: Union[int, str, Decimal]) -> None:
    if isinstance(elem, int):
        return

    for _ in range(3):
        if isinstance(elem, (Decimal, int)) and elem > 10:
            continue
        reveal_type(elem)
        elem += 1   # new compared to the example above

    return None

mypy:

$ mypy example.py
example.py:11: note: Revealed type is "Union[builtins.str, decimal.Decimal]"  # correct
example.py:11: note: Revealed type is "Union[builtins.int, Any, builtins.str, decimal.Decimal]"  # even wider, now including Any
example.py:12: error: Unsupported operand types for + ("str" and "int")   # expected and correct
example.py:12: note: Left operand is of type "Union[str, Decimal]"
example.py:12: note: Left operand is of type "Union[int, Any, str, Decimal]"
Found 1 error in 1 file (checked 1 source file)

(In this example, it's trivial to get around the problem by removing the redundant isinstance(int) check, but in our actual code, it wasn't so straightforward.)

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 eseguendo le riproduzioni Python fornite con mypy, inclusa la variante con elem += 1, e confronta gli output duplicati di reveal_type. La correzione è completa quando ogni chiamata a reveal_type produce un risultato che mantiene il restringimento iniziale e le diagnosi di controllo dei tipi associate rimangono corrette.

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
38/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.