python / python/mypy

Declaration-order-dependent possibly-undefined false positive with nested ifs/matches, decorated any functions and NoReturn

Offen
#17,895 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

bug
Vorherrschende Sprache
Python
Sterne
20.6k
Forks
3.3k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

Bug Report

Some obtuse code results in a false positive for the possibly-undefined error code.

To Reproduce

Run mypy --enable-error-code possibly-undefined file.py on this file:

decorator = lambda f: f


def unreachable() -> None:
    raise NotImplementedError()


def do_it(x: bool, y: None) -> None:
    if x:
        decorated()
        var = 0
    else:
        match y:
            case None:
                var = 1
            case _:
                unreachable()
    print(var)


@decorator
def decorated() -> None:
    pass

This is as small as I've gotten the reproducer. All these parts seem to be significant:

  • the outer if and an inner match
  • the decorated call being separate to the match
  • the match being a match (replacing the match with the equivalent if y is None: ... else: ... construct works fine)
  • the match having exhaustive arms with the unreachable call being unreachable (as far as mypy can tell) (e.g. deleting the case None: entirely works fine)
  • the unreachable call existing (inlining case _: raise NotImplementedError() works fine)
  • decorator being a lambda (or an class with __call__ method) (using def decorator(f): return f works fine)
  • decorated being defined after do_it in the file (changing the order works fine) (NB. it's just decorated, decorator and unreachable can be defined before or after do_it and still reproduce the behaviour)

Expected Behavior

This to pass type checking.

In particular, have same behaviour as any of the very similar ablations mentioned above, e.g. both of these work:

  • changing decorator = lambda f: f to def decorator(f): return f
  • moving decorated to be before do_it

Actual Behavior

file.py:19: error: Name "var" may be undefined  [possibly-undefined]
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 1.11.2
  • Mypy command-line flags: --enable-error-code possibly-undefined
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.10

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne mit dem minimalen file.py-Reproducer und führe mypy --enable-error-code possibly-undefined aus, um die gemeldete Diagnose zu bestätigen. Vergleiche die aufgeführten Ablationen, einschließlich der Decorator-Definition, der Deklarationsreihenfolge und der match-Zweige, um die Interaktion zu isolieren. Als abgeschlossen gilt die Aufgabe, wenn der Reproducer die Typprüfung ohne den False Positive besteht.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
devtools
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
42/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.