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

0.940: Condition can't be inferred, unable to merge overloads #12335

Closed
twoertwein opened this issue Mar 11, 2022 · 7 comments · Fixed by #12336
Closed

0.940: Condition can't be inferred, unable to merge overloads #12335

twoertwein opened this issue Mar 11, 2022 · 7 comments · Fixed by #12336
Labels
bug mypy got something wrong

Comments

@twoertwein
Copy link

twoertwein commented Mar 11, 2022

Bug Report
This might be an issue with beartype, it has been reported there beartype/beartype#112. Since mypy reports an overload error at a line that has no overloads, it might be a mypy error (edit: there are overloads around).

To Reproduce

from beartype import beartype

@beartype
def test(x: int) -> int:
    return x

/home/twoertwe/.cache/pypoetry/virtualenvs/python-tools-sgDWaTGJ-py3.10/lib/python3.10/site-packages/beartype/_decor/main.py:294: error: Condition can't be inferred, unable to merge overloads [misc]

The line in question is here:
https://github.com/beartype/beartype/blob/main/beartype/_decor/main.py#L294

Expected Behavior
Either no error or a better indication at which line the error occurs.

Your Environment

  • Mypy version used: 0.940
  • Mypy command-line flags: -
  • Mypy configuration options from mypy.ini (and other config files): -
  • Python version used: 3.10.2
  • Operating system and version: Ubuntu
@twoertwein twoertwein added the bug mypy got something wrong label Mar 11, 2022
@cdce8p
Copy link
Collaborator

cdce8p commented Mar 11, 2022

Thanks for the message. I'll take a look

@cdce8p
Copy link
Collaborator

cdce8p commented Mar 11, 2022

I was able to reproduce the issue and opened #12336 to fix it. Thanks again. Some more details below.

The error message is caused by this If statement

if (
    not __debug__ or
    TYPE_CHECKING
): ...

Mypy can only infer a very limited number of conditions and variables. __debug__ isn't one of them, see also here. In your particular case, you can actual work around that by switching the conditionals, i.e. TYPE_CHECKING or not __debug__.

@leycec
Copy link

leycec commented Mar 11, 2022

@beartype guy here. Thanks so much for the zero-day hot fix, @cdce8p. That's super-sized tech support right there. I never would have thought to try the ol' switcheroo. 🥲

@leycec
Copy link

leycec commented Mar 11, 2022

Urk. Reversing the order of those conditions does resolve the exact issue in question – but then explosively emits two new errors and one warning concerning the same if conditional:

beartype/_decor/main.py:71: error: The implementation for an overloaded function must come last  [misc]
beartype/_decor/main.py:329: error: Overloaded function implementation cannot satisfy signature 2 due to inconsistencies in how they use type variables  [misc]
beartype/_decor/main.py:329: note: Error code "misc" not covered by "type: ignore" comment
Found 2 errors in 1 file (checked 166 source files)

It's one stunningly bold leap forward, three awkward drunken stumbles backward. On the bright side, we'd been meaning to fundamentally refactor and optimize all of this logic anyway. On the dark side, we're lazy and tired and it's blizzarding outside. Canada: the tireless journey continues.

@cdce8p
Copy link
Collaborator

cdce8p commented Mar 12, 2022

These error messages appear to be correct as far as I can tell. Tbh even the current solution only works because of a type: ignore[no-redef]. I would suggest a refactoring.

Maybe something like this might work? That would actually need conditional overloads, i.e. 0.940.

@overload
def beartype(obj: BeartypeableT) -> BeartypeableT: ...
@overload
def beartype(*, conf: BeartypeConf) -> BeartypeConfedDecorator: ...
if (TYPE_CHECKING or __debug__):
    def beartype(
        # Optional positional or keyword parameters.
        obj: Optional[BeartypeableT] = None,

        # Optional keyword-only parameters.
        *,
        conf: BeartypeConf = BeartypeConf(),
    ) -> Union[BeartypeableT, BeartypeConfedDecorator]:
        ...

        return beartype_confed
else:
    # The type here is still wrong, but since mypy can infer the first conditional (with `TYPE_CHECKING`)
    # this will never be checked or used (by mypy)
    def beartype(  # type: ignore[no-redef]
        obj: BeartypeableT,

        # Optional keyword-only parameters.
        *,
        conf: BeartypeConf = BeartypeConf(),
    ) -> BeartypeableT:

        return obj

@leycec
Copy link

leycec commented Mar 12, 2022

These error messages appear to be correct as far as I can tell.

Absolutely. I hope I didn't suggest otherwise. You've been amazingly helpful. And much to my continual chagrin, mypy's usually in the right. I was just hoping to get some productive volunteerism done tonight. Though... I suppose this is technically productive. 😮‍💨

That would actually need conditional overloads, i.e. 0.940.

...excellent! I wasn't sure whether that would work. I'm tremendously relieved that it does and more than happy to mandate downstream use of mypy ≥ 0.940.

Thanks again for all the apropos suggestions, @cdce8p.

@leycec
Copy link

leycec commented Mar 12, 2022

Resolved downstream in beartype/beartype#113. 👍 😴

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

Successfully merging a pull request may close this issue.

3 participants