Skip to content

fix for all_of expects Matcher[Never] #266

@bukzor

Description

@bukzor

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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions