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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions