-
Notifications
You must be signed in to change notification settings - Fork 117
Open
Description
Below is my simulation of Matcher/all_of using Wrap/wrap_all. The added overloads
change the apparent semantics, but only in a way that better matches how the typechecker evaluates the possibilities. It also prevents mypy
from deciding that this case is too ambiguous and settling on T = Never
.
from typing import Generic
from typing import TypeVar
from typing import overload
T = TypeVar("T")
class Wrap(Generic[T]):
def __init__(self, t: T):
self.t = t
@overload
def wrap_all(*items: Wrap[T]) -> Wrap[T]: ...
@overload
def wrap_all(*items: T) -> Wrap[T]: ...
def wrap_all(*items: Wrap[T] | T) -> Wrap[T]:
for item in items:
if isinstance(item, Wrap):
return item
else:
return Wrap(item)
else:
raise ValueError(items)
def test_cases() -> None:
# Case 1: All wrapped - matches first overload
result1 = wrap_all(Wrap({1: 2}), Wrap({3: 4})) # Should work!
reveal_type(result1)
# Case 2: All unwrapped - matches second overload
result2 = wrap_all({1: 2}, {3: 4}) # Should work!
reveal_type(result2)
# Case 3: Single wrapped - matches first overload
result3 = wrap_all(Wrap({1: 2})) # Should work!
reveal_type(result3)
# Case 4: Single unwrapped - matches second overload
result4 = wrap_all({1: 2}) # Should work!
reveal_type(result4)
# Mixed case: This would fall back to implementation signature
# and potentially fail type checking (which is probably good!)
result5 = wrap_all(Wrap({1: 2}), {3: 4}) # Unclear semantics anyway
reveal_type(result5)
__BEFORE__ = """\
error: Need type annotation for "result1" [var-annotated]
error: Argument 1 to "wrap_all" has incompatible type "Wrap[dict[int, int]]"; expected "Wrap[Never]" [arg-type]
error: Argument 2 to "wrap_all" has incompatible type "Wrap[dict[int, int]]"; expected "Wrap[Never]" [arg-type]
note: Revealed type is "demo.Wrap[Any]"
note: Revealed type is "demo.Wrap[builtins.dict[builtins.int, builtins.int]]"
error: Need type annotation for "result3" [var-annotated]
error: Argument 1 to "wrap_all" has incompatible type "Wrap[dict[int, int]]"; expected "Wrap[Never]" [arg-type]
note: Revealed type is "demo.Wrap[Any]"
note: Revealed type is "demo.Wrap[builtins.dict[builtins.int, builtins.int]]"
note: Revealed type is "demo.Wrap[builtins.dict[builtins.int, builtins.int]]"
Found 5 errors in 1 file (checked 1 source file)
"""
__AFTER__ = """\
note: Revealed type is "demo.Wrap[builtins.dict[builtins.int, builtins.int]]"
note: Revealed type is "demo.Wrap[builtins.dict[builtins.int, builtins.int]]"
note: Revealed type is "demo.Wrap[builtins.dict[builtins.int, builtins.int]]"
note: Revealed type is "demo.Wrap[builtins.dict[builtins.int, builtins.int]]"
note: Revealed type is "demo.Wrap[builtins.object]"
Success: no issues found in 1 source file
"""
Metadata
Metadata
Assignees
Labels
No labels