Skip to content

false positive: "Overloaded function signatures ... overlap with incompatible return types" #11165

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

Open
finite-state-machine opened this issue Sep 21, 2021 · 5 comments
Labels
bug mypy got something wrong topic-overloads

Comments

@finite-state-machine
Copy link

finite-state-machine commented Sep 21, 2021

Bug Report

Code of a certain form causes a false positive error:

error: Overloaded function signatures 1 and 2 overlap with incompatible return types  [misc]

To Reproduce

Gist: mypy-play.net

from typing import (
        Literal,
        overload,
        Sequence,
        TypeVar,
        Union,
        )

T1 = TypeVar('T1')
T2 = TypeVar('T2')

@overload
def func(a1: Literal[True], a2: T1) -> Union[T1, Sequence[T2]]: ...
    # error: Overloaded function signatures 1 and 2 overlap with incompatible return types  [misc]

@overload
def func(a1: bool, a2: T1) -> Union[T1, Sequence[T2], T2]: ...

def func(  # type: ignore[empty-body]
        a1: bool, a2: T1) -> Union[T1, Sequence[T2], T2]:
    ...

Expected Behavior

There should be no errors.

  • the second signature's arguments are clearly broader than the first's (bool vs. Literal[True])
  • the second signature's return type is clearly broader than the first's (Union[...] vs. Union[..., T2])

Actual Behavior

An error is issued:

error: Overloaded function signatures 1 and 2 overlap with incompatible return types  [misc]

Additional notes

This example is fairly minimal:

  • removing the a2 argument from all three declarations causes the problem to disappear
  • removing the Sequence[T2] clause from the return Union of all three declarations causes the problem to disappear

Your Environment

  • Mypy version used: 0.910, 1.8.0
  • Mypy command-line flags: (none)
  • Mypy configuration options from mypy.ini (and other config files): (none)
  • Python version used: 3.8, 3.12
@finite-state-machine finite-state-machine added the bug mypy got something wrong label Sep 21, 2021
@Dr-Irv
Copy link

Dr-Irv commented Oct 12, 2021

The following example may be related. It is something we are trying to get working with respect to pandas stubs supplied by Microsoft with VS Code. Full discussion microsoft/python-type-stubs#87

Goal is to have two parameters i1 that is bool and cs that is Optional[int] that may or may not be specified. Issue with mypy is that it is saying that None and int overlap. Goal of the code below is to have results corresponding to the table below:

i1 cs Return Type
Not specified Not specified int
False Not specified int
False None int
False An integer str
True Not specified str
True None str
True An integer str
Not specified None int
Not specified An integer str
@overload
def myfun(fake: str, i1: Literal[True], cs: Union[int, None] = ...) -> str:
    ...


@overload
def myfun(fake: str, i1: Literal[False], cs: int) -> str:
    ...


@overload
def myfun(fake: str, i1: Literal[False] = ..., cs: None = ...) -> int:
    ...


@overload
def myfun(fake: str, i1: bool = ..., cs: int = ...) -> str:
    ...


def myfun(fake: str, i1: bool = False, cs: Optional[int] = None) -> Union[str, int]:
    print(f"i1 is {i1} cs is {cs} result is ", end="")
    if i1:
        if cs is not None:
            return "TextFileReader"
        else:
            return "TextFileReader"
    else:
        if cs is not None:
            return "TextFileReader"
        else:
            return -1


res1: int = myfun("meh")
res2: int = myfun("meh", i1=False)
res3: int = myfun("meh", i1=False, cs=None)
res4: str = myfun("meh", i1=False, cs=23)
res5: str = myfun("meh", i1=True)
res6: str = myfun("meh", i1=True, cs=None)
res7: str = myfun("meh", i1=True, cs=23)
res8: int = myfun("meh", cs=None)
res9: str = myfun("meh", cs=23)

mypy version 0.910 complains as follows:

error: Overloaded function signatures 3 and 4 overlap with incompatible return types

The pyright type checker does not have this complaint.

@erictraut
Copy link

I think what's confusing mypy is the fact that cs has a default argument in overloads 3 and 4. We can eliminate that requirement if i1 and cs are keyword-only parameters by making the following change. This works fine in both mypy and pyright.

@overload
def myfun(fake: str, *, i1: Literal[True], cs: int | None = ...) -> str:
    ...


@overload
def myfun(fake: str, *, i1: Literal[False], cs: int) -> str:
    ...


@overload
def myfun(fake: str, *, i1: Literal[False] = ..., cs: None = ...) -> int:
    ...


@overload
def myfun(fake: str, *, i1: bool = ..., cs: int) -> str:
    ...


def myfun(fake: str, i1: bool = False, cs: Optional[int] = None) -> Union[str, int]:
    print(f"i1 is {i1} cs is {cs} result is ", end="")
    if i1:
        if cs is not None:
            return "TextFileReader"
        else:
            return "TextFileReader"
    else:
        if cs is not None:
            return "TextFileReader"
        else:
            return -1


res1: int = myfun("meh")
res2: int = myfun("meh", i1=False)
res3: int = myfun("meh", i1=False, cs=None)
res4: str = myfun("meh", i1=False, cs=23)
res5: str = myfun("meh", i1=True)
res6: str = myfun("meh", i1=True, cs=None)
res7: str = myfun("meh", i1=True, cs=23)
res8: int = myfun("meh", cs=None)
res9: str = myfun("meh", cs=23)

@finite-state-machine
Copy link
Author

  • verified to affect mypy 1.8.0 on Python 3.12
  • refreshed reproduction case to account for an unrelated issue (fixed), new warning (empty-body)
  • added mypy-play[.]net gist link to bug description

@jamesbraza
Copy link
Contributor

Possibly related: #6580

@rpgoldman
Copy link

I think this is another example:

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

6 participants