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

Different overlap checking between __mul__ and __rmul__ #18498

Open
leamingrad opened this issue Jan 21, 2025 · 1 comment · May be fixed by #18502
Open

Different overlap checking between __mul__ and __rmul__ #18498

leamingrad opened this issue Jan 21, 2025 · 1 comment · May be fixed by #18502
Labels
bug mypy got something wrong

Comments

@leamingrad
Copy link

leamingrad commented Jan 21, 2025

Bug Report

When attempting to add overrides to the __mul__ and __rmul__ magic methods, different behaviour is observed for the same set of overrides.

This seems similar to the issue in #10755, but that has since been fixed.

To Reproduce

Playground link: https://mypy-play.net/?mypy=latest&python=3.12&gist=1297febcc3b38a2eea422e7073842c31

(Note that this playground is for the latest version (1.14.1), but the same errors are observed on master)

Sample program:

from typing import TypeVar, overload
from decimal import Decimal

TAmount = TypeVar("TAmount", int, Decimal)


class Unit:
    @overload
    def __mul__(self, other: Unit) -> Unit: ...
    @overload
    def __mul__(self, other: TAmount) -> Quantity[TAmount]: ...

    def __mul__(self, other: Unit | TAmount) -> Unit | Quantity[TAmount]:
        raise NotImplementedError

    @overload
    def __rmul__(self, other: Unit) -> Unit: ...
    @overload
    def __rmul__(self, other: TAmount) -> Quantity[TAmount]: ...

    def __rmul__(self, other: Unit | TAmount) -> Unit | Quantity[TAmount]:
        raise NotImplementedError


class Quantity[TAmount]:
    def __init__(self, value: TAmount, units: Unit) -> None:
        self.value = value
        self.units = units

Expected Behavior

I expect this program to typecheck successfull (or error for both __mul__ and __rmul__)

Actual Behavior

main.py:22: error: Signatures of "__rmul__" of "Unit" and "__mul__" of "Unit | int" are unsafely overlapping  [misc]
main.py:22: error: Signatures of "__rmul__" of "Unit" and "__mul__" of "Unit | Decimal" are unsafely overlapping  [misc]
Found 2 errors in 1 file (checked 1 source file)
@leamingrad leamingrad added the bug mypy got something wrong label Jan 21, 2025
@sterliakov
Copy link
Collaborator

This can be minimized without typevars to the following:

from typing import overload

class Unit:
    @overload
    def __mul__(self, other: Unit) -> Unit: ...
    @overload
    def __mul__(self, other: int) -> str: ...
    def __mul__(self, other: Unit | int) -> Unit | str:
        if isinstance(other, Unit): return Unit()
        return 'foo'

    @overload
    def __rmul__(self, other: Unit) -> Unit: ...
    @overload
    def __rmul__(self, other: int) -> str: ...
    def __rmul__(self, other: Unit | int) -> Unit | str:
        if isinstance(other, Unit): return Unit()
        return 'foo'

The problem is that we check __rmul__ implementation signature as well as both overloads, this should not happen normally.

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.

2 participants