python / python/mypy

`@overload` breaks with named tuple and some overloaded functions

Abierto
#10,470 1 comentario 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

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

Descripción

Bug Report

Mypy incorrectly reports Any as the resolved type (quite possibly due this https://github.com/python/typing/issues/253#issuecomment-235358878 )

To Reproduce

from collections import namedtuple
from typing import Any, Callable, cast, Dict, List, NamedTuple, overload, TypeVar, Union

F = TypeVar("F", bound=Callable[..., Any])
Arg: NamedTuple = namedtuple("Arg", ["arg"])


class Test:
    @overload
    def __call__(self, fn: F) -> F:
        ...

    @overload
    def __call__(self, *args: Any, **kwargs: Any) -> "Test":
        ...

    def __call__(self, *args: Any, **kwargs: Any) -> Union[F, "Test"]:
        if len(args) == 1:
            return cast(F, args[0])

        return self

reveal_type(Test()(Test))



def broken(arg: Arg) -> Arg:
    return arg

reveal_type(broken)
reveal_type(Test()(broken))



def working(arg: int) -> int:
    return arg

reveal_type(Test()(working))



@overload
def overloaded_broken(arg: F) -> F:
    ...

@overload
def overloaded_broken(*args: Any, **kwargs: Any) -> Dict[str, int]:
    ...

def overloaded_broken(*args: Any, **kwargs: Any) -> Union[F, Dict[str, int]]:
    if len(args) == 1:
        return cast(F, args[0])

    return dict(args=len(args), kwargs=len(kwargs))


reveal_type(overloaded_broken)
reveal_type(Test()(overloaded_broken))


@overload
def overloaded_working(arg: str) -> str:
    ...

@overload
def overloaded_working(arg: bytes) -> bytes:
    ...

def overloaded_working(arg: Union[bytes, str]) -> Union[bytes, str]:
    return arg


reveal_type(Test()(overloaded_working))

Expected Behavior

All revealed types are printed as non Any

Actual Behavior

# a class is OK
test.py:23:13: note: Revealed type is 'def () -> test.Test'

# this is what is expected when using a named tuple, but it resolves as any
test.py:30:13: note: Revealed type is 'def (arg: Tuple[Any, fallback=test.Arg]) -> Tuple[Any, fallback=test.Arg]'
test.py:31:13: note: Revealed type is 'Any'

# this is not using a named tuple and it works as expected
test.py:38:13: note: Revealed type is 'def (arg: builtins.int) -> builtins.int'

# this is what is expected for a complex overloaded function, but it resolves as any
test.py:57:13: note: Revealed type is 'Overload(def [F <: def (*Any, **Any) -> Any] (arg: F`-1) -> F`-1, def (*args: Any, **kwargs: Any) -> builtins.dict[builtins.str, builtins.int])'
test.py:58:13: note: Revealed type is 'Any'

# passing a simpler overloaded function
test.py:73:13: note: Revealed type is 'Overload(def (arg: builtins.str) -> builtins.str, def (arg: builtins.bytes) -> builtins.bytes)'

Your Environment

mypy --version: mypy 0.812 (default config)
python --version: Python 3.8.9

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 ejecutando la reproducción en test.py con mypy 0.812 y compara los revealed types para los casos named-tuple y overloaded-function. Rastrea la resolución de sobrecargas y el tratamiento de los tipos named-tuple, y luego verifica que los reveals afectados se resuelvan en sus tipos callable esperados en lugar de Any.

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

Evaluación

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

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.