Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions conformance/results/mypy/overloads_evaluation.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ notes = """
Does not expand boolean arguments to `Literal[True]` and `Literal[False]`.
Does not expand enum arguments to literal variants.
Does not expand tuple arguments to possible combinations.
Does not evaluate `Any` in some cases where overload is ambiguous.
Evaluates `Any` in some cases where overload is not ambiguous.
"""
conformance_automated = "Fail"
Expand All @@ -14,10 +13,7 @@ Line 161: Unexpected errors ['overloads_evaluation.py:161: error: No overload va
Line 162: Unexpected errors ['overloads_evaluation.py:162: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type]']
Line 205: Unexpected errors ['overloads_evaluation.py:205: error: Argument 1 to "expand_tuple" has incompatible type "tuple[int, int | str]"; expected "tuple[int, int]" [arg-type]']
Line 206: Unexpected errors ['overloads_evaluation.py:206: error: Expression is of type "int", not "int | str" [assert-type]']
Line 265: Unexpected errors ['overloads_evaluation.py:265: error: Expression is of type "list[Any]", not "Any" [assert-type]']
Line 281: Unexpected errors ['overloads_evaluation.py:281: error: Expression is of type "list[Any]", not "Any" [assert-type]']
Line 303: Unexpected errors ['overloads_evaluation.py:303: error: Expression is of type "Any", not "float" [assert-type]']
Line 347: Unexpected errors ['overloads_evaluation.py:347: error: Expression is of type "list[Any]", not "Any" [assert-type]']
Line 312: Unexpected errors ['overloads_evaluation.py:312: error: Expression is of type "Any", not "float" [assert-type]']
"""
output = """
overloads_evaluation.py:38: error: All overload variants of "example1_1" require at least one argument [call-overload]
Expand Down Expand Up @@ -46,8 +42,5 @@ overloads_evaluation.py:161: note: def expand_enum(x: Literal[Color.BLUE]) -
overloads_evaluation.py:162: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type]
overloads_evaluation.py:205: error: Argument 1 to "expand_tuple" has incompatible type "tuple[int, int | str]"; expected "tuple[int, int]" [arg-type]
overloads_evaluation.py:206: error: Expression is of type "int", not "int | str" [assert-type]
overloads_evaluation.py:265: error: Expression is of type "list[Any]", not "Any" [assert-type]
overloads_evaluation.py:281: error: Expression is of type "list[Any]", not "Any" [assert-type]
overloads_evaluation.py:303: error: Expression is of type "Any", not "float" [assert-type]
overloads_evaluation.py:347: error: Expression is of type "list[Any]", not "Any" [assert-type]
overloads_evaluation.py:312: error: Expression is of type "Any", not "float" [assert-type]
"""
9 changes: 6 additions & 3 deletions conformance/results/pyright/overloads_evaluation.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
conformant = "Partial"
notes = """
Does not evaluate `Any` in some cases where overload is ambiguous.
Infers `list[int]` for ambiguous overloads with `list[Any]` arguments, rejecting use as `list[str]`.
"""
conformance_automated = "Fail"
errors_diff = """
Line 281: Unexpected errors ['overloads_evaluation.py:281:17 - error: "assert_type" mismatch: expected "Any" but received "list[int]" (reportAssertTypeFailure)']
Line 290: Unexpected errors ['overloads_evaluation.py:290:27 - error: Type "list[int]" is not assignable to declared type "list[str]"']
"""
output = """
overloads_evaluation.py:38:1 - error: No overloads for "example1_1" match the provided arguments
Expand All @@ -20,5 +20,8 @@ overloads_evaluation.py:116:14 - error: Argument of type "int | str" cannot be a
overloads_evaluation.py:116:17 - error: Argument of type "int | str" cannot be assigned to parameter "y" of type "int" in function "example2"
  Type "int | str" is not assignable to type "int"
    "str" is not assignable to "int" (reportArgumentType)
overloads_evaluation.py:281:17 - error: "assert_type" mismatch: expected "Any" but received "list[int]" (reportAssertTypeFailure)
overloads_evaluation.py:290:27 - error: Type "list[int]" is not assignable to declared type "list[str]"
  "list[int]" is not assignable to "list[str]"
    Type parameter "_T@list" is invariant, but "int" is not the same as "str"
    Consider switching from "list" to "Sequence" which is covariant (reportAssignmentType)
"""
3 changes: 1 addition & 2 deletions conformance/results/results.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 25 additions & 3 deletions conformance/tests/overloads_evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,12 @@ def check_variadic(v: list[int]) -> None:
# > :term:`materializations <materialize>` of the argument's type are assignable to
# > the corresponding parameter type for each of the remaining overloads. If so,
# > eliminate all of the subsequent remaining overloads.
# >
# > If the return types are not equivalent, overload matching is ambiguous. In
# > this case, infer a return type that is :term:`assignable` to each of the
# > remaining return types and permits operations supported by any of them without
# > errors, then stop. A type checker may infer ``Any`` or a more precise gradual
# > type that satisfies these requirements.


@overload
Expand All @@ -262,7 +268,8 @@ def check_example4(v1: list[Any], v2: Any) -> None:
assert_type(ret1, list[int])

ret2 = example4(v2, 1)
assert_type(ret2, Any)
int_list: list[int] = ret2
str_list: list[str] = ret2


@overload
Expand All @@ -278,7 +285,9 @@ def example5(obj: Any) -> list[Any]:


def check_example5(b: list[Any]) -> None:
assert_type(example5(b), Any)
ret = example5(b)
int_list: list[int] = ret
str_list: list[str] = ret


@overload
Expand Down Expand Up @@ -344,4 +353,17 @@ def check_example7(v1: list[Any], v2: Any) -> None:
assert_type(ret2, list[str])

ret3 = example7(v1, v2)
assert_type(ret3, Any)
int_list: list[int] = ret3
str_list: list[str] = ret3


# The earlier ambiguity cases check assignability of list return types. This
# checks distinct scalar return types and operations specific to each type.


def check_ambiguous_scalar_return(v: Any) -> None:
ret = example2(1, v, 1)
int_result: int = ret
str_result: str = ret
_ = ret + 1
ret.upper()
13 changes: 11 additions & 2 deletions docs/spec/overload.rst
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,15 @@ they should be replaced with their solved types. If the resulting return types
for all remaining overloads are :term:`equivalent`, proceed to step 6.

If the return types are not equivalent, overload matching is ambiguous. In
this case, assume a return type of ``Any`` and stop.
this case, infer a return type that is :term:`assignable` to each of the
remaining return types and permits operations supported by any of them without
errors, then stop. A type checker may infer ``Any`` or a more precise gradual
type that satisfies these requirements.

For example, if the remaining return types are ``int`` and ``str``, the result
should be assignable to both ``int`` and ``str``, and both ``result + 1`` and
``result.upper()`` should be accepted. Inferring the ordinary union ``int | str``
would not satisfy these requirements.

Step 6
~~~~~~
Expand Down Expand Up @@ -395,7 +403,8 @@ Example 4::
# both apply and are ambiguous due to Any, and
# the return types are inconsistent.
r2 = example4(v2, 1)
reveal_type(r2) # Should reveal Any
int_result: int = r2 # OK
list_result: list[int] = r2 # OK


.. _argument-type-expansion:
Expand Down