mypy icon indicating copy to clipboard operation
mypy copied to clipboard

Mypy doesn't recognize accept a callable result type when type hint allows any result type

Open EldarSehayekZenity opened this issue 3 years ago • 0 comments

Bug Report

When a decorator function hinted to return a callable with any result type effectively returns a callable with more specific return type there's a mypy error.

To Reproduce

  1. Write this code:
_PRouteParams = ParamSpec("_PRouteParams")
def decorate_me(func: Callable[Concatenate[int, _PRouteParams], Any]) -> Callable[Concatenate[int, _PRouteParams], Any]:
        def inner(x: int, *args: _PRouteParams.args, **kwargs: _PRouteParams.kwargs) -> dict[str, Any]:
            return {"result": func(x, *args, **kwargs)}

        return inner
  1. Run mypy on above code with "strict=True"

Expected Behavior

I expect mypy to not have errors for above code because a a callable that returns any type T, in above example T=dict[str, Any], satisfies being a callable that returns Any.

More generally speaking, if a decorator should return a callable with return type T1 and T2 inherits from T1 then a callable returning T2 should be allowed to be returned by that decorator.

Actual Behavior

Mypy emits error:

error: Incompatible return value type (got "Callable[[int, **_PRouteParams], Dict[str, Any]]", expected "Callable[[int, **_PRouteParams], Any]") src\zenity\infra\common\decorators\zenity_api.py:55: note: This may be because "inner" has arguments named: "x"

Your Environment

  • Mypy version used: 0.971
  • Mypy command-line flags: N/A
  • Mypy configuration options from mypy.ini (and other config files):

follow_imports = "normal" ignore_errors = false implicit_reexport = false warn_redundant_casts = true warn_unused_ignores = true disallow_any_generics = true disallow_untyped_defs = true check_untyped_defs = true allow_redefinition = false local_partial_types = true strict_optional = true strict_equality = true warn_unused_configs = true warn_unreachable = true warn_no_return = true no_implicit_optional = true strict = true

  • Python version used: 3.10.4
  • Operating system and version: Windows 11

EldarSehayekZenity avatar Sep 23 '22 00:09 EldarSehayekZenity