python / python/mypy

Incorrectly narrowed Literal in while loops

Aperta
#17,096 4 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

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

Descrizione

Bug Report

The following code snippet:

from typing import Literal


class Node:
    color: Literal["red", "black"]
    next: Node


def walk(node: Node) -> None:
    while node.color == "red":
        node = node.next
    reveal_type(node.color)
    while True:
        reveal_type(node.color)
        if node.color == "red":
            return
        node = node.next
        reveal_type(node.color)

Results in a comparison-overlap false positive under mypy --strict:

test.py:12: note: Revealed type is "Literal['black']"
test.py:14: note: Revealed type is "Literal['black']"
test.py:15: error: Non-overlapping equality check (left operand type: "Literal['black']", right operand type: "Literal['red']")  [comparison-overlap]
test.py:18: note: Revealed type is "Union[Literal['red'], Literal['black']]"
Found 1 error in 1 file (checked 1 source file)

As you can see, mypy correctly concludes that at line 12, node.color must be "black", and at line 18, it may be "red" or "black". But at line 14, it still thinks that it must be "black" even though it may not be on subsequent iterations. This causes the false positive on line 15.

To Reproduce

https://mypy-play.net/?mypy=master&python=3.12&flags=strict&gist=3207b91810da9f447ff090d86df689a5

Your Environment

  • Mypy version used: tested on 1.10.0+dev.80190101f68b52e960c22572ed6cc814de078b9c and 1.8.0
  • Mypy command-line flags: --strict
  • Mypy configuration options from mypy.ini (and other config files): N/A
  • Python version used: 3.12.2

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

Riproduci lo snippet con mypy --strict e confronta il narrowing nei tre punti reveal_type. Traccia il flusso di controllo e la logica di narrowing del ciclo while; il lavoro è completato quando il secondo ciclo non mantiene il narrowing del primo ciclo, l’errore di sovrapposizione nel confronto scompare e i tipi rivelati corrispondono al report.

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.