python / python/mypy

Type narrowing for Optional[T] fails inside an else branch inside a while cycle

Aperta
#11,947 0 commenti 1 reazione 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

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

Descrizione

Bug Report

from typing import Optional                                                      
                                                                                 
                                                                                 
class Node:                                                                      
    def __init__(self, value: int):                                      
        self.value = value                                                       
        self.next: Optional[Node] = None                                         
                                                                                 
                                                                                 
def foo(node: Node) -> None:                                                     
    while node.next is not None:                                                 
        if node.value != node.next.value:                                        
            node = node.next                                                     
        else:                                                                    
            node.next = node.next.next   # <-- HERE

Expected Behavior

No mypy errors. Mypy should know that node.next is not None in the else branch.

Actual Behavior

Mypy says error: Item "None" of "Optional[Node]" has no attribute "next" on the line marked by <-- HERE. (With column numbers turned on, the location is the beginning of node.next.next.)

Interestingly, everything is OK if the branches of if are reversed:

def foo(node: Node) -> None:                                                     
    while node.next is not None:                                                 
        if node.value == node.next.value:                                        
            node.next = node.next.next                                           
        else:                                                                    
            node = node.next                                                     

Writing assert node is not None before the problematic line also fixes the error (but seems quite redundant).

Your Environment

  • Mypy version used: mypy 0.930
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): default, no config files
  • Python version used: Python 3.10.1
  • Operating system and version: Arch Linux

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 mypy 0.930 senza configurazione sull’esempio Optional[Node] nell’issue, quindi confronta i due ordinamenti dei rami e la variante con assert. Traccia il restringimento del tipo attorno alla condizione while e all’assegnazione; il lavoro è concluso quando l’esempio originale non segnala alcun errore senza l’assert ridondante.

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

Valutazione

Stack tecnologico
python
Ambito
compilers
Tipo di issue
Bug
Difficoltà
3/5
Tempo stimato
1-2 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.