`Union[type[...], ...]` and `type` not the same as `type[...]`, `...`, and `type`
sylvorg opened this issue · comments
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!
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.