Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
finite-state-machine opened this issue Apr 26, 2022 · 3 comments
Labels
bug mypy got something wrong topic-overloads

Comments

@finite-state-machine
Copy link

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
@finite-state-machine finite-state-machine added the bug mypy got something wrong label Apr 26, 2022
@AlexWaygood
Copy link
Member

Looks like this has already been brought up in the big functools.partial tracking issue here #1484 (comment) -- maybe it might be better to leave a comment on that issue, to keep all the functools.partial discussion in one place?

@finite-state-machine
Copy link
Author

Looks like this has already been brought up in the big functools.partial tracking issue here #1484 (comment) -- maybe it might be better to leave a comment on that issue, to keep all the functools.partial discussion in one place?

My apologies, I didn't search comments on existing issues before filing. If, in your best judgment, this issue should be closed as duplicate, I have no objection.

@AlexWaygood
Copy link
Member

No worries! Yes, I think it's best to keep all the functools.partial discussion in one place :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-overloads
Projects
None yet
Development

No branches or pull requests

2 participants