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

Union[type[...], ...] and type not the same as type[...], ..., and type #149

Open
sylvorg opened this issue May 3, 2024 · 1 comment
Open

Comments

@sylvorg
Copy link

sylvorg commented May 3, 2024

Hello!

With the following code:

from plum import dispatch
from typing import Union

class Test: pass

test = Test()

@dispatch
def a(testing: Union[type[Test], Test]):
    print(Union[type[Test], Test])

@dispatch
def a(testing: type):
    print(type)

@dispatch
def b(testing: type[Test]):
    print(type[Test])

@dispatch
def b(testing: Test):
    print(Test)

@dispatch
def b(testing: type):
    print(type)

b(Test)
b(test)
a(Test)
a(test)

a is giving me an AmbiguousLookupError:

Traceback (most recent call last):
  File "/mnt/wsl/sylvorg/sylvorg/sylveon/siluam/oreo/./test23.py", line 33, in <module>
    a(Test)
  File "/nix/store/04jyrbixnk1n5c5cn1lcv6p1j98nmwxf-python3-3.11.8-env/lib/python3.11/site-packages/plum/function.py", line 367, in __call__
    method, return_type = self._resolve_method_with_cache(args=args)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/04jyrbixnk1n5c5cn1lcv6p1j98nmwxf-python3-3.11.8-env/lib/python3.11/site-packages/plum/function.py", line 398, in _resolve_method_with_cache
    method, return_type = self.resolve_method(args)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/04jyrbixnk1n5c5cn1lcv6p1j98nmwxf-python3-3.11.8-env/lib/python3.11/site-packages/plum/function.py", line 310, in resolve_method
    raise e from None
  File "/nix/store/04jyrbixnk1n5c5cn1lcv6p1j98nmwxf-python3-3.11.8-env/lib/python3.11/site-packages/plum/function.py", line 300, in resolve_method
    method = self._resolver.resolve(target)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/04jyrbixnk1n5c5cn1lcv6p1j98nmwxf-python3-3.11.8-env/lib/python3.11/site-packages/plum/resolver.py", line 334, in resolve
    raise AmbiguousLookupError(self.function_name, target, candidates)
plum.resolver.AmbiguousLookupError: `a(<class '__main__.Test'>)` is ambiguous.

Candidates:
   a(testing: typing.Union[type[__main__.Test], __main__.Test])
       <function a at 0x7f992f091300> @ ~/sylvorg/sylveon/siluam/oreo/./test23.py:11
   a(testing: type)
       <function a at 0x7f992f091440> @ ~/sylvorg/sylveon/siluam/oreo/./test23.py:15

Shouldn't Union function the same as separate definitions?

Thank you kindly for the help!

@wesselb
Copy link
Member

wesselb commented May 18, 2024

Hey @sylvorg!

Union does not quite function as separate definitions. What's going on here is the following:

type is not a subtype of Union[type[Test], Test], because it is strictly more general than Test. In addition, Union[type[Test], Test] is not a subtype of type, because Test (which matches objects) is not a substype of type (which matches types):

>>> from beartype.door import TypeHint

>>> TypeHint(Union[type[Test], Test]) <= TypeHint(type)
False

>>> TypeHint(Union[type[Test], Test]) >= TypeHint(type)
False

Therefore, neither signature is more specific than the other, so Plum will not automatically narrow it down. If you input matches both signatures, Plum will throw an ambiguity error, as in the above example.

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

No branches or pull requests

2 participants