Mypy does not correctly narrow indexing operations when using Literal or Final keys
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Python
- Estrellas
- 20.6k
- Forks
- 3.3k
- Métricas de merge de PR
- Métricas de PR pendientes
Descripción
Consider the following program:
from typing_extensions import Literal, TypedDict
from enum import Enum
class Key(Enum):
X = 1
Y = 2
Z = 3
class MyDict(TypedDict):
key: Literal[Key.X, Key.Y]
blah: int
KEY: Literal["key"] = "key"
d: MyDict
if d["key"] is Key.X:
reveal_type(d["key"]) # note: Revealed type is 'Literal[Key.X]'
if d[KEY] is Key.X:
reveal_type(d[KEY]) # note: Revealed type is 'Literal[Key.X, Key.Y]'
Mypy is currently capable of narrowing expressions like d["key"], which we can see in the first expression.
So, it's natural to assume that mypy would be able to do the same for the second since the two programs are theoretically identical -- but we can't.
The root cause has to do with the "literal" subsystem (which is not to be confused with the Literal types subsystem) here: https://github.com/python/mypy/blob/master/mypy/literals.py#L65
The index in the second example is a NameExpr, which causes the if statement to evaluate to false and return a LITERAL_NO. This then makes the narrowing logic rule out d[KEY] as a candidate for narrowing in https://github.com/python/mypy/blob/master/mypy/checker.py#L3775.
I'm not really sure what the best way of fixing this would be. The natural solution would be to also pass along the expression type into the literal(...) function, but that seems very annoying to do. I'm also not entirely sure whether this is even a sound narrowing: I'm not very familiar with the "literals" subsystem, or how it's meant to interact with Literal types.
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Comienza con la reproducción del issue y luego inspecciona mypy/literals.py alrededor de literal() y mypy/checker.py alrededor de la lógica de narrowing en la línea 3775. Sigue el motivo por el que un NameExpr para KEY produce LITERAL_NO y compáralo con el índice de cadena directo. Terminado cuando el caso KEY reduzca d[KEY] a Literal[Key.X] de forma consistente con d["key"].
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
- Tranquilo
- Claridad
- Bastante claro
- Aptitud para principiantes
- 48/100