python / python/mypy

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

Abierto
#17,895 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

bug
Lenguaje dominante
Python
Estrellas
20.6k
Forks
3.3k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

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

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Empieza con el reproductor mínimo file.py y ejecuta mypy --enable-error-code possibly-undefined para confirmar el diagnóstico indicado. Compara las ablaciones enumeradas, incluida la definición del decorador, el orden de las declaraciones y las ramas de match, para aislar la interacción. Se considera terminado cuando el reproductor supera la comprobación de tipos sin el falso positivo.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
python
Área
devtools
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
42/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.