Skip to content

functools.partial always assumes the first signature of an @overloaded function #12675

Closed
@finite-state-machine

Description

Bug Report

When functools.partial() is applied to an overloaded function, the return type of the first @overload signature is always assumed.

To Reproduce

import functools
from typing import (
        Literal,
        overload,
        Union,
        )

@overload
def function(a: Literal[True]) -> int: ...
@overload
def function(a: Literal[False] = False) -> str: ...

def function(a: bool = False) -> Union[int, str]:
    if a:
        return 42
    else:
        return 'hello'

p0 = functools.partial(function)
reveal_type(p0)
        # actual: Revealed type is "functools.partial[builtins.int*]"
        # expected: Revealed type is "functools.partial[Union[int, str]]"
        # (because 'p0()' would accept any value for 'a')

v0 = p0()
reveal_type(v0)
        # actual: Revealed type is "builtins.int*"
        # expected: either "str" or "Union[int, str]"
        # (the latter is less precise, but at least it's not wrong)

p1 = functools.partial(function, a=False)
reveal_type(p1)
        # actual: Revealed type is "functools.partial[builtins.int*]"
        # expected: Revealed type is "functools.partial[Union[int, str]]"
        # (because 'p1()' can still accept any value for 'a' if given as a kwarg;
        # 'functools.partial()' defaults can be overridden)

p2 = functools.partial(function, a=True)
reveal_type(p2)
        # actual: Revealed type is "functools.partial[builtins.int*]"
        # expected: Revealed type is "functools.partial[Union[int, str]]"
        # (by similar logic)

Expected Behavior

If mypy cannot intelligently handle the interaction of @overload and functools.partial() (i.e., the partial object has overloaded behaviour), it should at least assume the return type of the partial is that of the @overloaded function's implementation (e.g. Union[int, str]). Assuming the return type of the first @overloaded signature is unsound.

Actual Behavior

mypy seems to assume the partial object has the return type of the first @overloaded signature, regardless of the arguments. Other signatures and the implementation signature are ignored.

Your Environment

  • Mypy version used: 0.942
  • Mypy command-line flags: (none)
  • Mypy configuration options from mypy.ini (and other config files): (none)
  • Python version used: 3.8
  • Operating system and version: macOS 10.14

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions