From cf93e8230778cba1cffe1a5709687aa02e00aac5 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Mon, 31 Mar 2025 19:01:28 -0700 Subject: [PATCH 1/2] Added a few more overload evaluation tests. These uncovered a few more cases where mypy and pyright do not conform to the standard. --- .../results/mypy/overloads_evaluation.toml | 74 ++++--- .../results/pyre/overloads_evaluation.toml | 64 +++--- conformance/results/pyre/version.toml | 2 +- .../results/pyright/overloads_evaluation.toml | 21 +- .../results/pytype/overloads_evaluation.toml | 135 +++++++----- conformance/results/pytype/version.toml | 2 +- conformance/results/results.html | 8 +- conformance/tests/overloads_evaluation.py | 204 ++++++++++++++---- 8 files changed, 340 insertions(+), 170 deletions(-) diff --git a/conformance/results/mypy/overloads_evaluation.toml b/conformance/results/mypy/overloads_evaluation.toml index b1d7d783..f2899d8b 100644 --- a/conformance/results/mypy/overloads_evaluation.toml +++ b/conformance/results/mypy/overloads_evaluation.toml @@ -3,41 +3,51 @@ 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 is some cases where overload is not ambiguous. """ conformance_automated = "Fail" errors_diff = """ -Line 106: Unexpected errors ['overloads_evaluation.py:106: error: No overload variant of "expand_bool" matches argument type "bool" [call-overload]'] -Line 107: Unexpected errors ['overloads_evaluation.py:107: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type]'] -Line 129: Unexpected errors ['overloads_evaluation.py:129: error: No overload variant of "expand_enum" matches argument type "Color" [call-overload]'] -Line 130: Unexpected errors ['overloads_evaluation.py:130: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type]'] -Line 169: Unexpected errors ['overloads_evaluation.py:169: error: Argument 1 to "expand_tuple" has incompatible type "tuple[int, int | str]"; expected "tuple[int, int]" [arg-type]'] -Line 170: Unexpected errors ['overloads_evaluation.py:170: error: Expression is of type "int", not "int | str" [assert-type]'] +Line 134: Unexpected errors ['overloads_evaluation.py:134: error: No overload variant of "expand_bool" matches argument type "bool" [call-overload]'] +Line 135: Unexpected errors ['overloads_evaluation.py:135: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type]'] +Line 160: Unexpected errors ['overloads_evaluation.py:160: error: No overload variant of "expand_enum" matches argument type "Color" [call-overload]'] +Line 161: Unexpected errors ['overloads_evaluation.py:161: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type]'] +Line 204: Unexpected errors ['overloads_evaluation.py:204: error: Argument 1 to "expand_tuple" has incompatible type "tuple[int, int | str]"; expected "tuple[int, int]" [arg-type]'] +Line 205: Unexpected errors ['overloads_evaluation.py:205: error: Expression is of type "int", not "int | str" [assert-type]'] +Line 264: Unexpected errors ['overloads_evaluation.py:264: error: Expression is of type "list[Any]", not "Any" [assert-type]'] +Line 280: Unexpected errors ['overloads_evaluation.py:280: error: Expression is of type "list[Any]", not "Any" [assert-type]'] +Line 298: Unexpected errors ['overloads_evaluation.py:298: error: Expression is of type "Any", not "float" [assert-type]'] +Line 336: Unexpected errors ['overloads_evaluation.py:336: error: Expression is of type "list[Any]", not "Any" [assert-type]'] """ output = """ -overloads_evaluation.py:32: error: All overload variants of "example1" require at least one argument [call-overload] -overloads_evaluation.py:32: note: Possible overload variants: -overloads_evaluation.py:32: note: def example1(x: int, y: str) -> int -overloads_evaluation.py:32: note: def example1(x: str) -> str -overloads_evaluation.py:40: error: No overload variant of "example1" matches argument types "int", "int" [call-overload] -overloads_evaluation.py:40: note: Possible overload variants: -overloads_evaluation.py:40: note: def example1(x: int, y: str) -> int -overloads_evaluation.py:40: note: def example1(x: str) -> str -overloads_evaluation.py:45: error: No overload variant of "example1" matches argument type "int" [call-overload] -overloads_evaluation.py:45: note: Possible overload variants: -overloads_evaluation.py:45: note: def example1(x: int, y: str) -> int -overloads_evaluation.py:45: note: def example1(x: str) -> str -overloads_evaluation.py:89: error: Argument 1 to "example2" has incompatible type "int | str"; expected "int" [arg-type] -overloads_evaluation.py:89: error: Argument 2 to "example2" has incompatible type "int | str"; expected "str" [arg-type] -overloads_evaluation.py:106: error: No overload variant of "expand_bool" matches argument type "bool" [call-overload] -overloads_evaluation.py:106: note: Possible overload variants: -overloads_evaluation.py:106: note: def expand_bool(x: Literal[False]) -> Literal[0] -overloads_evaluation.py:106: note: def expand_bool(x: Literal[True]) -> Literal[1] -overloads_evaluation.py:107: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type] -overloads_evaluation.py:129: error: No overload variant of "expand_enum" matches argument type "Color" [call-overload] -overloads_evaluation.py:129: note: Possible overload variants: -overloads_evaluation.py:129: note: def expand_enum(x: Literal[Color.RED]) -> Literal[0] -overloads_evaluation.py:129: note: def expand_enum(x: Literal[Color.BLUE]) -> Literal[1] -overloads_evaluation.py:130: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type] -overloads_evaluation.py:169: error: Argument 1 to "expand_tuple" has incompatible type "tuple[int, int | str]"; expected "tuple[int, int]" [arg-type] -overloads_evaluation.py:170: error: Expression is of type "int", not "int | str" [assert-type] +overloads_evaluation.py:38: error: All overload variants of "example1_1" require at least one argument [call-overload] +overloads_evaluation.py:38: note: Possible overload variants: +overloads_evaluation.py:38: note: def example1_1(x: int, y: str) -> int +overloads_evaluation.py:38: note: def example1_1(x: str) -> str +overloads_evaluation.py:46: error: No overload variant of "example1_1" matches argument types "int", "int" [call-overload] +overloads_evaluation.py:46: note: Possible overload variants: +overloads_evaluation.py:46: note: def example1_1(x: int, y: str) -> int +overloads_evaluation.py:46: note: def example1_1(x: str) -> str +overloads_evaluation.py:51: error: No overload variant of "example1_1" matches argument type "int" [call-overload] +overloads_evaluation.py:51: note: Possible overload variants: +overloads_evaluation.py:51: note: def example1_1(x: int, y: str) -> int +overloads_evaluation.py:51: note: def example1_1(x: str) -> str +overloads_evaluation.py:115: error: Argument 1 to "example2" has incompatible type "int | str"; expected "int" [arg-type] +overloads_evaluation.py:115: error: Argument 2 to "example2" has incompatible type "int | str"; expected "str" [arg-type] +overloads_evaluation.py:134: error: No overload variant of "expand_bool" matches argument type "bool" [call-overload] +overloads_evaluation.py:134: note: Possible overload variants: +overloads_evaluation.py:134: note: def expand_bool(x: Literal[False]) -> Literal[0] +overloads_evaluation.py:134: note: def expand_bool(x: Literal[True]) -> Literal[1] +overloads_evaluation.py:135: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type] +overloads_evaluation.py:160: error: No overload variant of "expand_enum" matches argument type "Color" [call-overload] +overloads_evaluation.py:160: note: Possible overload variants: +overloads_evaluation.py:160: note: def expand_enum(x: Literal[Color.RED]) -> Literal[0] +overloads_evaluation.py:160: note: def expand_enum(x: Literal[Color.BLUE]) -> Literal[1] +overloads_evaluation.py:161: error: Expression is of type "Any", not "Literal[0, 1]" [assert-type] +overloads_evaluation.py:204: error: Argument 1 to "expand_tuple" has incompatible type "tuple[int, int | str]"; expected "tuple[int, int]" [arg-type] +overloads_evaluation.py:205: error: Expression is of type "int", not "int | str" [assert-type] +overloads_evaluation.py:264: error: Expression is of type "list[Any]", not "Any" [assert-type] +overloads_evaluation.py:280: error: Expression is of type "list[Any]", not "Any" [assert-type] +overloads_evaluation.py:298: error: Expression is of type "Any", not "float" [assert-type] +overloads_evaluation.py:336: error: Expression is of type "list[Any]", not "Any" [assert-type] """ diff --git a/conformance/results/pyre/overloads_evaluation.toml b/conformance/results/pyre/overloads_evaluation.toml index 9a848686..c70070c2 100644 --- a/conformance/results/pyre/overloads_evaluation.toml +++ b/conformance/results/pyre/overloads_evaluation.toml @@ -9,35 +9,41 @@ Does not treat multiple matches due to gradual types as ambiguous. """ conformance_automated = "Fail" errors_diff = """ -Line 81: Unexpected errors ['overloads_evaluation.py:81:23 Incompatible parameter type [6]: In call `example2`, for 2nd positional argument, expected `str` but got `Union[int, str]`.'] -Line 82: Unexpected errors ['overloads_evaluation.py:82:4 Assert type [70]: Expected `Union[int, str]` but got `str`.'] -Line 106: Unexpected errors ['overloads_evaluation.py:106:23 Incompatible parameter type [6]: In call `expand_bool`, for 1st positional argument, expected `typing_extensions.Literal[False]` but got `bool`.'] -Line 107: Unexpected errors ['overloads_evaluation.py:107:4 Assert type [70]: Expected `Union[typing_extensions.Literal[0], typing_extensions.Literal[1]]` but got `typing_extensions.Literal[0]`.'] -Line 129: Unexpected errors ['overloads_evaluation.py:129:23 Incompatible parameter type [6]: In call `expand_enum`, for 1st positional argument, expected `typing_extensions.Literal[Color.RED]` but got `Color`.'] -Line 130: Unexpected errors ['overloads_evaluation.py:130:4 Assert type [70]: Expected `Union[typing_extensions.Literal[0], typing_extensions.Literal[1]]` but got `typing_extensions.Literal[0]`.'] -Line 147: Unexpected errors ['overloads_evaluation.py:147:29 Incompatible parameter type [6]: In call `expand_type_union`, for 1st positional argument, expected `Type[int]` but got `Type[Union[int, str]]`.'] -Line 148: Unexpected errors ['overloads_evaluation.py:148:4 Assert type [70]: Expected `Union[int, str]` but got `int`.'] -Line 169: Unexpected errors ['overloads_evaluation.py:169:24 Incompatible parameter type [6]: In call `expand_tuple`, for 1st positional argument, expected `Tuple[int, int]` but got `Tuple[int, Union[int, str]]`.'] -Line 170: Unexpected errors ['overloads_evaluation.py:170:4 Assert type [70]: Expected `Union[int, str]` but got `int`.'] -Line 196: Unexpected errors ['overloads_evaluation.py:196:4 Assert type [70]: Expected `int` but got `str`.'] -Line 224: Unexpected errors ['overloads_evaluation.py:224:4 Assert type [70]: Expected `typing.Any` but got `int`.'] +Line 105: Unexpected errors ['overloads_evaluation.py:105:23 Incompatible parameter type [6]: In call `example2`, for 2nd positional argument, expected `str` but got `Union[int, str]`.'] +Line 106: Unexpected errors ['overloads_evaluation.py:106:4 Assert type [70]: Expected `Union[int, str]` but got `str`.'] +Line 134: Unexpected errors ['overloads_evaluation.py:134:23 Incompatible parameter type [6]: In call `expand_bool`, for 1st positional argument, expected `typing_extensions.Literal[False]` but got `bool`.'] +Line 135: Unexpected errors ['overloads_evaluation.py:135:4 Assert type [70]: Expected `Union[typing_extensions.Literal[0], typing_extensions.Literal[1]]` but got `typing_extensions.Literal[0]`.'] +Line 160: Unexpected errors ['overloads_evaluation.py:160:23 Incompatible parameter type [6]: In call `expand_enum`, for 1st positional argument, expected `typing_extensions.Literal[Color.RED]` but got `Color`.'] +Line 161: Unexpected errors ['overloads_evaluation.py:161:4 Assert type [70]: Expected `Union[typing_extensions.Literal[0], typing_extensions.Literal[1]]` but got `typing_extensions.Literal[0]`.'] +Line 180: Unexpected errors ['overloads_evaluation.py:180:29 Incompatible parameter type [6]: In call `expand_type_union`, for 1st positional argument, expected `Type[int]` but got `Type[Union[int, str]]`.'] +Line 181: Unexpected errors ['overloads_evaluation.py:181:4 Assert type [70]: Expected `Union[int, str]` but got `int`.'] +Line 204: Unexpected errors ['overloads_evaluation.py:204:24 Incompatible parameter type [6]: In call `expand_tuple`, for 1st positional argument, expected `Tuple[int, int]` but got `Tuple[int, Union[int, str]]`.'] +Line 205: Unexpected errors ['overloads_evaluation.py:205:4 Assert type [70]: Expected `Union[int, str]` but got `int`.'] +Line 234: Unexpected errors ['overloads_evaluation.py:234:4 Assert type [70]: Expected `int` but got `str`.'] +Line 264: Unexpected errors ['overloads_evaluation.py:264:4 Assert type [70]: Expected `typing.Any` but got `List[int]`.'] +Line 280: Unexpected errors ['overloads_evaluation.py:280:4 Assert type [70]: Expected `typing.Any` but got `List[int]`.'] +Line 307: Unexpected errors ["overloads_evaluation.py:307:4 Assert type [70]: Expected `str` but got `typing_extensions.Literal['']`."] +Line 336: Unexpected errors ['overloads_evaluation.py:336:4 Assert type [70]: Expected `typing.Any` but got `List[int]`.'] """ output = """ -overloads_evaluation.py:32:0 Missing argument [20]: Call `example1` expects argument `x`. -overloads_evaluation.py:40:12 Incompatible parameter type [6]: In call `example1`, for 2nd positional argument, expected `str` but got `int`. -overloads_evaluation.py:45:9 Incompatible parameter type [6]: In call `example1`, for 1st positional argument, expected `str` but got `int`. -overloads_evaluation.py:81:23 Incompatible parameter type [6]: In call `example2`, for 2nd positional argument, expected `str` but got `Union[int, str]`. -overloads_evaluation.py:82:4 Assert type [70]: Expected `Union[int, str]` but got `str`. -overloads_evaluation.py:89:13 Incompatible parameter type [6]: In call `example2`, for 1st positional argument, expected `int` but got `Union[int, str]`. -overloads_evaluation.py:89:16 Incompatible parameter type [6]: In call `example2`, for 2nd positional argument, expected `str` but got `Union[int, str]`. -overloads_evaluation.py:106:23 Incompatible parameter type [6]: In call `expand_bool`, for 1st positional argument, expected `typing_extensions.Literal[False]` but got `bool`. -overloads_evaluation.py:107:4 Assert type [70]: Expected `Union[typing_extensions.Literal[0], typing_extensions.Literal[1]]` but got `typing_extensions.Literal[0]`. -overloads_evaluation.py:129:23 Incompatible parameter type [6]: In call `expand_enum`, for 1st positional argument, expected `typing_extensions.Literal[Color.RED]` but got `Color`. -overloads_evaluation.py:130:4 Assert type [70]: Expected `Union[typing_extensions.Literal[0], typing_extensions.Literal[1]]` but got `typing_extensions.Literal[0]`. -overloads_evaluation.py:147:29 Incompatible parameter type [6]: In call `expand_type_union`, for 1st positional argument, expected `Type[int]` but got `Type[Union[int, str]]`. -overloads_evaluation.py:148:4 Assert type [70]: Expected `Union[int, str]` but got `int`. -overloads_evaluation.py:169:24 Incompatible parameter type [6]: In call `expand_tuple`, for 1st positional argument, expected `Tuple[int, int]` but got `Tuple[int, Union[int, str]]`. -overloads_evaluation.py:170:4 Assert type [70]: Expected `Union[int, str]` but got `int`. -overloads_evaluation.py:196:4 Assert type [70]: Expected `int` but got `str`. -overloads_evaluation.py:224:4 Assert type [70]: Expected `typing.Any` but got `int`. +overloads_evaluation.py:38:0 Missing argument [20]: Call `example1_1` expects argument `x`. +overloads_evaluation.py:46:14 Incompatible parameter type [6]: In call `example1_1`, for 2nd positional argument, expected `str` but got `int`. +overloads_evaluation.py:51:11 Incompatible parameter type [6]: In call `example1_1`, for 1st positional argument, expected `str` but got `int`. +overloads_evaluation.py:105:23 Incompatible parameter type [6]: In call `example2`, for 2nd positional argument, expected `str` but got `Union[int, str]`. +overloads_evaluation.py:106:4 Assert type [70]: Expected `Union[int, str]` but got `str`. +overloads_evaluation.py:115:13 Incompatible parameter type [6]: In call `example2`, for 1st positional argument, expected `int` but got `Union[int, str]`. +overloads_evaluation.py:115:16 Incompatible parameter type [6]: In call `example2`, for 2nd positional argument, expected `str` but got `Union[int, str]`. +overloads_evaluation.py:134:23 Incompatible parameter type [6]: In call `expand_bool`, for 1st positional argument, expected `typing_extensions.Literal[False]` but got `bool`. +overloads_evaluation.py:135:4 Assert type [70]: Expected `Union[typing_extensions.Literal[0], typing_extensions.Literal[1]]` but got `typing_extensions.Literal[0]`. +overloads_evaluation.py:160:23 Incompatible parameter type [6]: In call `expand_enum`, for 1st positional argument, expected `typing_extensions.Literal[Color.RED]` but got `Color`. +overloads_evaluation.py:161:4 Assert type [70]: Expected `Union[typing_extensions.Literal[0], typing_extensions.Literal[1]]` but got `typing_extensions.Literal[0]`. +overloads_evaluation.py:180:29 Incompatible parameter type [6]: In call `expand_type_union`, for 1st positional argument, expected `Type[int]` but got `Type[Union[int, str]]`. +overloads_evaluation.py:181:4 Assert type [70]: Expected `Union[int, str]` but got `int`. +overloads_evaluation.py:204:24 Incompatible parameter type [6]: In call `expand_tuple`, for 1st positional argument, expected `Tuple[int, int]` but got `Tuple[int, Union[int, str]]`. +overloads_evaluation.py:205:4 Assert type [70]: Expected `Union[int, str]` but got `int`. +overloads_evaluation.py:234:4 Assert type [70]: Expected `int` but got `str`. +overloads_evaluation.py:264:4 Assert type [70]: Expected `typing.Any` but got `List[int]`. +overloads_evaluation.py:280:4 Assert type [70]: Expected `typing.Any` but got `List[int]`. +overloads_evaluation.py:307:4 Assert type [70]: Expected `str` but got `typing_extensions.Literal['']`. +overloads_evaluation.py:336:4 Assert type [70]: Expected `typing.Any` but got `List[int]`. """ diff --git a/conformance/results/pyre/version.toml b/conformance/results/pyre/version.toml index b7e0e78a..94de3055 100644 --- a/conformance/results/pyre/version.toml +++ b/conformance/results/pyre/version.toml @@ -1,2 +1,2 @@ version = "pyre 0.9.23" -test_duration = 6.3 +test_duration = 7.3 diff --git a/conformance/results/pyright/overloads_evaluation.toml b/conformance/results/pyright/overloads_evaluation.toml index 2c490190..7f7e0dce 100644 --- a/conformance/results/pyright/overloads_evaluation.toml +++ b/conformance/results/pyright/overloads_evaluation.toml @@ -1,19 +1,24 @@ -conformant = "Pass" -conformance_automated = "Pass" +conformant = "Partial" +notes = """ +Does not evaluate Any in some cases where overload is ambiguous. +""" +conformance_automated = "Fail" errors_diff = """ +Line 280: Unexpected errors ['overloads_evaluation.py:280:17 - error: "assert_type" mismatch: expected "Any" but received "list[int]" (reportAssertTypeFailure)'] """ output = """ -overloads_evaluation.py:32:1 - error: No overloads for "example1" match the provided arguments +overloads_evaluation.py:38:1 - error: No overloads for "example1_1" match the provided arguments   Argument types: () (reportCallIssue) -overloads_evaluation.py:40:13 - error: Argument of type "Literal[1]" cannot be assigned to parameter "y" of type "str" in function "example1" +overloads_evaluation.py:46:15 - error: Argument of type "Literal[1]" cannot be assigned to parameter "y" of type "str" in function "example1_1"   "Literal[1]" is not assignable to "str" (reportArgumentType) -overloads_evaluation.py:45:10 - error: Argument of type "Literal[1]" cannot be assigned to parameter "x" of type "str" in function "example1" +overloads_evaluation.py:51:12 - error: Argument of type "Literal[1]" cannot be assigned to parameter "x" of type "str" in function "example1_1"   "Literal[1]" is not assignable to "str" (reportArgumentType) -overloads_evaluation.py:89:5 - error: No overloads for "example2" match the provided arguments (reportCallIssue) -overloads_evaluation.py:89:14 - error: Argument of type "int | str" cannot be assigned to parameter "x" of type "int" in function "example2" +overloads_evaluation.py:115:5 - error: No overloads for "example2" match the provided arguments (reportCallIssue) +overloads_evaluation.py:115:14 - error: Argument of type "int | str" cannot be assigned to parameter "x" 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:89:17 - error: Argument of type "int | str" cannot be assigned to parameter "y" of type "int" in function "example2" +overloads_evaluation.py:115: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:280:17 - error: "assert_type" mismatch: expected "Any" but received "list[int]" (reportAssertTypeFailure) """ diff --git a/conformance/results/pytype/overloads_evaluation.toml b/conformance/results/pytype/overloads_evaluation.toml index 004eea70..94f4f97c 100644 --- a/conformance/results/pytype/overloads_evaluation.toml +++ b/conformance/results/pytype/overloads_evaluation.toml @@ -6,131 +6,168 @@ Does not prefer variadic match to indeterminate-length unpacked argument. """ conformance_automated = "Fail" errors_diff = """ -Line 89: Expected 1 errors -Line 28: Unexpected errors ['overloads_evaluation.py:28:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in example1: bad return type [bad-return-type]'] -Line 63: Unexpected errors ['overloads_evaluation.py:63:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in example2: bad return type [bad-return-type]'] -Line 82: Unexpected errors ['overloads_evaluation.py:82:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_union: str [assert-type]'] -Line 103: Unexpected errors ['overloads_evaluation.py:103:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in expand_bool: bad return type [bad-return-type]', 'overloads_evaluation.py:103:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in expand_bool: bad return type [bad-return-type]'] -Line 106: Unexpected errors ['overloads_evaluation.py:106:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_bool: Function expand_bool was called with the wrong arguments [wrong-arg-types]'] -Line 107: Unexpected errors ['overloads_evaluation.py:107:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_bool: Any [assert-type]'] -Line 126: Unexpected errors ['overloads_evaluation.py:126:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in expand_enum: bad return type [bad-return-type]'] -Line 129: Unexpected errors ['overloads_evaluation.py:129:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_enum: Function expand_enum was called with the wrong arguments [wrong-arg-types]'] -Line 130: Unexpected errors ['overloads_evaluation.py:130:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_enum: Any [assert-type]'] -Line 144: Unexpected errors ['overloads_evaluation.py:144:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in expand_type_union: bad return type [bad-return-type]'] -Line 148: Unexpected errors ['overloads_evaluation.py:148:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_type_union: int [assert-type]'] -Line 166: Unexpected errors ['overloads_evaluation.py:166:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in expand_tuple: bad return type [bad-return-type]'] -Line 170: Unexpected errors ['overloads_evaluation.py:170:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_tuple: int [assert-type]'] -Line 188: Unexpected errors ['overloads_evaluation.py:188:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in variadic: bad return type [bad-return-type]'] -Line 196: Unexpected errors ['overloads_evaluation.py:196:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_variadic: str [assert-type]'] -Line 217: Unexpected errors ['overloads_evaluation.py:217:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in example4: bad return type [bad-return-type]'] -Line 224: Unexpected errors ['overloads_evaluation.py:224:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_example4: int [assert-type]'] +Line 115: Expected 1 errors +Line 33: Unexpected errors ['overloads_evaluation.py:33:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in example1_1: bad return type [bad-return-type]'] +Line 62: Unexpected errors ['overloads_evaluation.py:62:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in example1_2: bad return type [bad-return-type]', 'overloads_evaluation.py:62:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in example1_2: bad return type [bad-return-type]'] +Line 85: Unexpected errors ['overloads_evaluation.py:85:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in example2: bad return type [bad-return-type]'] +Line 106: Unexpected errors ['overloads_evaluation.py:106:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_union: str [assert-type]'] +Line 130: Unexpected errors ['overloads_evaluation.py:130:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in expand_bool: bad return type [bad-return-type]', 'overloads_evaluation.py:130:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in expand_bool: bad return type [bad-return-type]'] +Line 134: Unexpected errors ['overloads_evaluation.py:134:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_bool: Function expand_bool was called with the wrong arguments [wrong-arg-types]'] +Line 135: Unexpected errors ['overloads_evaluation.py:135:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_bool: Any [assert-type]'] +Line 156: Unexpected errors ['overloads_evaluation.py:156:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in expand_enum: bad return type [bad-return-type]'] +Line 160: Unexpected errors ['overloads_evaluation.py:160:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_enum: Function expand_enum was called with the wrong arguments [wrong-arg-types]'] +Line 161: Unexpected errors ['overloads_evaluation.py:161:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_enum: Any [assert-type]'] +Line 176: Unexpected errors ['overloads_evaluation.py:176:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in expand_type_union: bad return type [bad-return-type]'] +Line 181: Unexpected errors ['overloads_evaluation.py:181:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_type_union: int [assert-type]'] +Line 200: Unexpected errors ['overloads_evaluation.py:200:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in expand_tuple: bad return type [bad-return-type]'] +Line 205: Unexpected errors ['overloads_evaluation.py:205:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_expand_tuple: int [assert-type]'] +Line 224: Unexpected errors ['overloads_evaluation.py:224:12: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in variadic: bad return type [bad-return-type]'] +Line 234: Unexpected errors ['overloads_evaluation.py:234:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_variadic: str [assert-type]'] +Line 264: Unexpected errors ['overloads_evaluation.py:264:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_example4: list[int] [assert-type]'] +Line 280: Unexpected errors ['overloads_evaluation.py:280:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_example5: list[int] [assert-type]'] +Line 291: Unexpected errors ['overloads_evaluation.py:291:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in example6: bad return type [bad-return-type]', 'overloads_evaluation.py:291:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in example6: bad return type [bad-return-type]', 'overloads_evaluation.py:291:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in example6: bad return type [bad-return-type]'] +Line 336: Unexpected errors ['overloads_evaluation.py:336:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_example7: list[int] [assert-type]'] """ output = """ -overloads_evaluation.py:28:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in example1: bad return type [bad-return-type] +overloads_evaluation.py:33:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in example1_1: bad return type [bad-return-type] return 1 \u001b[1m\u001b[31m~\u001b[39m\u001b[0m Called from (traceback): - line 42, in current file -overloads_evaluation.py:32:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in : Missing parameter 'x' in call to function example1 [missing-parameter] + line 48, in current file +overloads_evaluation.py:38:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in : Missing parameter 'x' in call to function example1_1 [missing-parameter] -example1() # E: no matching overload -\u001b[1m\u001b[31m~~~~~~~~~~\u001b[39m\u001b[0m +example1_1() # E: no matching overload +\u001b[1m\u001b[31m~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:40:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in : Function example1 was called with the wrong arguments [wrong-arg-types] +overloads_evaluation.py:46:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in : Function example1_1 was called with the wrong arguments [wrong-arg-types] -example1(1, 1) # E: Literal[1] not assignable to str -\u001b[1m\u001b[31m~~~~~~~~~~~~~~\u001b[39m\u001b[0m +example1_1(1, 1) # E: Literal[1] not assignable to str +\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:45:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in : Function example1 was called with the wrong arguments [wrong-arg-types] +overloads_evaluation.py:51:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in : Function example1_1 was called with the wrong arguments [wrong-arg-types] -example1(1) # E: Literal[1] not assignable to str -\u001b[1m\u001b[31m~~~~~~~~~~~\u001b[39m\u001b[0m +example1_1(1) # E: Literal[1] not assignable to str +\u001b[1m\u001b[31m~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:63:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in example2: bad return type [bad-return-type] +overloads_evaluation.py:62:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in example1_2: bad return type [bad-return-type] + +def example1_2(b: bool = True) -> float: ... +\u001b[1m\u001b[31m\u001b[39m\u001b[0m + +overloads_evaluation.py:62:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in example1_2: bad return type [bad-return-type] + +def example1_2(b: bool = True) -> float: ... +\u001b[1m\u001b[31m\u001b[39m\u001b[0m + +overloads_evaluation.py:85:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in example2: bad return type [bad-return-type] return 1 \u001b[1m\u001b[31m~\u001b[39m\u001b[0m -overloads_evaluation.py:82:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_union: str [assert-type] +overloads_evaluation.py:106:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_union: str [assert-type] assert_type(ret1, int | str) \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:103:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in expand_bool: bad return type [bad-return-type] +overloads_evaluation.py:130:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in expand_bool: bad return type [bad-return-type] return int(x) \u001b[1m\u001b[31m~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:103:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in expand_bool: bad return type [bad-return-type] +overloads_evaluation.py:130:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in expand_bool: bad return type [bad-return-type] return int(x) \u001b[1m\u001b[31m~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:106:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_bool: Function expand_bool was called with the wrong arguments [wrong-arg-types] +overloads_evaluation.py:134:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_bool: Function expand_bool was called with the wrong arguments [wrong-arg-types] ret1 = expand_bool(v) \u001b[1m\u001b[31m~~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:107:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_bool: Any [assert-type] +overloads_evaluation.py:135:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_bool: Any [assert-type] assert_type(ret1, Literal[0, 1]) \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:126:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in expand_enum: bad return type [bad-return-type] +overloads_evaluation.py:156:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in expand_enum: bad return type [bad-return-type] return x.value \u001b[1m\u001b[31m~~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:129:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_enum: Function expand_enum was called with the wrong arguments [wrong-arg-types] +overloads_evaluation.py:160:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_enum: Function expand_enum was called with the wrong arguments [wrong-arg-types] ret1 = expand_enum(v) \u001b[1m\u001b[31m~~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:130:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_enum: Any [assert-type] +overloads_evaluation.py:161:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_enum: Any [assert-type] assert_type(ret1, Literal[0, 1]) \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:144:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in expand_type_union: bad return type [bad-return-type] +overloads_evaluation.py:176:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in expand_type_union: bad return type [bad-return-type] return 1 \u001b[1m\u001b[31m~\u001b[39m\u001b[0m -overloads_evaluation.py:148:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_type_union: int [assert-type] +overloads_evaluation.py:181:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_type_union: int [assert-type] assert_type(ret1, int | str) \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:166:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in expand_tuple: bad return type [bad-return-type] +overloads_evaluation.py:200:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in expand_tuple: bad return type [bad-return-type] return 1 \u001b[1m\u001b[31m~\u001b[39m\u001b[0m -overloads_evaluation.py:170:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_tuple: int [assert-type] +overloads_evaluation.py:205:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_expand_tuple: int [assert-type] assert_type(ret1, int | str) \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:188:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in variadic: bad return type [bad-return-type] +overloads_evaluation.py:224:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in variadic: bad return type [bad-return-type] return 1 \u001b[1m\u001b[31m~\u001b[39m\u001b[0m -overloads_evaluation.py:196:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_variadic: str [assert-type] +overloads_evaluation.py:234:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_variadic: str [assert-type] assert_type(ret1, int) \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:217:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in example4: bad return type [bad-return-type] +overloads_evaluation.py:264:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_example4: list[int] [assert-type] - return 1 - \u001b[1m\u001b[31m~\u001b[39m\u001b[0m + assert_type(ret2, Any) + \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m -overloads_evaluation.py:224:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_example4: int [assert-type] +overloads_evaluation.py:280:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_example5: list[int] [assert-type] - assert_type(ret2, Any) + assert_type(example5(b), Any) + \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m + +overloads_evaluation.py:291:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in example6: bad return type [bad-return-type] + +def example6(a: float, b: T) -> T: ... +\u001b[1m\u001b[31m\u001b[39m\u001b[0m + +Called from (traceback): + line 312, in check_example6 +overloads_evaluation.py:291:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in example6: bad return type [bad-return-type] + +def example6(a: float, b: T) -> T: ... +\u001b[1m\u001b[31m\u001b[39m\u001b[0m + +Called from (traceback): + line 306, in check_example6 +overloads_evaluation.py:291:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in example6: bad return type [bad-return-type] + +def example6(a: float, b: T) -> T: ... +\u001b[1m\u001b[31m\u001b[39m\u001b[0m + +overloads_evaluation.py:336:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_example7: list[int] [assert-type] + + assert_type(ret3, Any) \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m """ diff --git a/conformance/results/pytype/version.toml b/conformance/results/pytype/version.toml index e114259d..ec1b4602 100644 --- a/conformance/results/pytype/version.toml +++ b/conformance/results/pytype/version.toml @@ -1,2 +1,2 @@ version = "pytype 2024.10.11" -test_duration = 34.0 +test_duration = 33.4 diff --git a/conformance/results/results.html b/conformance/results/results.html index 955525fb..954bf6b7 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -165,10 +165,10 @@

Python Type System Conformance Test Results

1.3sec
pyre 0.9.23
-
6.3sec
+
7.3sec
pytype 2024.10.11
-
34.0sec
+
33.4sec
@@ -691,8 +691,8 @@

Python Type System Conformance Test Results

Fail

Does not enforce any of the specified rules regarding overload definitions.

     overloads_evaluation -
Partial

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.

-Pass +
Partial

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 is some cases where overload is not ambiguous.

+
Partial

Does not evaluate Any in some cases where overload is ambiguous.

Partial

Does not expand boolean arguments to Literal[True] and Literal[False].

Does not expand enum arguments to literal variants.

Does not expand type[A | B] to type[A] and type[B].

Does not expand tuple arguments to possible combinations.

Does not prefer variadic match to indeterminate-length unpacked argument.

Does not treat multiple matches due to gradual types as ambiguous.

Partial

Does not perform argument expansion (on any types) when matching overloads.

Does not treat multiple matches due to gradual types as ambiguous.

Does not prefer variadic match to indeterminate-length unpacked argument.

diff --git a/conformance/tests/overloads_evaluation.py b/conformance/tests/overloads_evaluation.py index 1c14cbd2..4d1ff18d 100644 --- a/conformance/tests/overloads_evaluation.py +++ b/conformance/tests/overloads_evaluation.py @@ -3,8 +3,12 @@ """ from enum import Enum -from typing import Any, assert_type, Literal, overload +from typing import Any, assert_type, Literal, overload, TypeVar +# mypy: disable-error-code=overload-overlap + + +T = TypeVar("T") # > Step 1: Examine the argument list to determine the number of # > positional and keyword arguments. Use this information to eliminate any @@ -16,33 +20,50 @@ # the separation of step 1 from step 2 is purely a presentation choice for the # algorithm, not a conformance requirement.) + @overload -def example1(x: int, y: str) -> int: - ... +def example1_1(x: int, y: str) -> int: ... + @overload -def example1(x: str) -> str: - ... +def example1_1(x: str) -> str: ... + -def example1(x: int | str, y: str = "") -> int | str: +def example1_1(x: int | str, y: str = "") -> int | str: return 1 + # > - If no candidate overloads remain, generate an error and stop. -example1() # E: no matching overload +example1_1() # E: no matching overload # > - If only one candidate overload remains, it is the winning match. Evaluate # > it as if it were a non-overloaded function call and stop. -ret1 = example1(1, "") +ret1 = example1_1(1, "") assert_type(ret1, int) -example1(1, 1) # E: Literal[1] not assignable to str +example1_1(1, 1) # E: Literal[1] not assignable to str -ret3 = example1("") +ret3 = example1_1("") assert_type(ret3, str) -example1(1) # E: Literal[1] not assignable to str +example1_1(1) # E: Literal[1] not assignable to str + + +@overload +def example1_2(b: Literal[True] = ...) -> int: ... + + +@overload +def example1_2(b: bool) -> float: ... + + +def example1_2(b: bool = True) -> float: ... + + +def check_example1_2() -> None: + assert_type(example1_2(), int) # > Step 2: Evaluate each remaining overload as a regular (non-overloaded) @@ -51,17 +72,19 @@ def example1(x: int | str, y: str = "") -> int | str: # > and arguments. During this step, do not generate any user-visible errors. # > Simply record which of the overloads result in evaluation errors. + @overload -def example2(x: int, y: str, z: int) -> str: - ... +def example2(x: int, y: str, z: int) -> str: ... + @overload -def example2(x: int, y: int, z: int) -> int: - ... +def example2(x: int, y: int, z: int) -> int: ... + def example2(x: int, y: int | str, z: int) -> int | str: return 1 + # > - If only one overload evaluates without error, it is the winning match. # > Evaluate it as if it were a non-overloaded function call and stop. @@ -77,31 +100,36 @@ def example2(x: int, y: int | str, z: int) -> int | str: # > respective return types by union to determine the final return type # > for the call, and stop. + def check_expand_union(v: int | str) -> None: ret1 = example2(1, v, 1) assert_type(ret1, int | str) + # > - If argument expansion has been applied to all arguments and one or # > more of the expanded argument lists cannot be evaluated successfully, # > generate an error and stop. + def check_expand_union_2(v: int | str) -> None: example2(v, v, 1) # E: no overload matches (str, ..., ...) # > 2. ``bool`` should be expanded into ``Literal[True]`` and ``Literal[False]``. + @overload -def expand_bool(x: Literal[False]) -> Literal[0]: - ... +def expand_bool(x: Literal[False]) -> Literal[0]: ... + @overload -def expand_bool(x: Literal[True]) -> Literal[1]: - ... +def expand_bool(x: Literal[True]) -> Literal[1]: ... + def expand_bool(x: bool) -> int: return int(x) + def check_expand_bool(v: bool) -> None: ret1 = expand_bool(v) assert_type(ret1, Literal[0, 1]) @@ -110,21 +138,24 @@ def check_expand_bool(v: bool) -> None: # > 3. ``Enum`` types (other than those that derive from ``enum.Flag``) should # > be expanded into their literal members. + class Color(Enum): RED = 1 BLUE = 1 + @overload -def expand_enum(x: Literal[Color.RED]) -> Literal[0]: - ... +def expand_enum(x: Literal[Color.RED]) -> Literal[0]: ... + @overload -def expand_enum(x: Literal[Color.BLUE]) -> Literal[1]: - ... +def expand_enum(x: Literal[Color.BLUE]) -> Literal[1]: ... + def expand_enum(x: Color) -> int: return x.value + def check_expand_enum(v: Color) -> None: ret1 = expand_enum(v) assert_type(ret1, Literal[0, 1]) @@ -132,17 +163,19 @@ def check_expand_enum(v: Color) -> None: # > 4. ``type[A | B]`` should be expanded into ``type[A]`` and ``type[B]``. + @overload -def expand_type_union(x: type[int]) -> int: - ... +def expand_type_union(x: type[int]) -> int: ... + @overload -def expand_type_union(x: type[str]) -> str: - ... +def expand_type_union(x: type[str]) -> str: ... + def expand_type_union(x: type[int] | type[str]) -> int | str: return 1 + def check_expand_type_union(v: type[int | str]) -> None: ret1 = expand_type_union(v) assert_type(ret1, int | str) @@ -154,17 +187,19 @@ def check_expand_type_union(v: type[int | str]) -> None: # > ``(int, Literal[False])``, ``(str, Literal[True])``, and # > ``(str, Literal[False])``. + @overload -def expand_tuple(x: tuple[int, int]) -> int: - ... +def expand_tuple(x: tuple[int, int]) -> int: ... + @overload -def expand_tuple(x: tuple[int, str]) -> str: - ... +def expand_tuple(x: tuple[int, str]) -> str: ... + def expand_tuple(x: tuple[int, int | str]) -> int | str: return 1 + def check_expand_tuple(v: int | str) -> None: ret1 = expand_tuple((1, v)) assert_type(ret1, int | str) @@ -176,49 +211,126 @@ def check_expand_tuple(v: int | str) -> None: # > that supplies an indeterminate number of positional or keyword arguments. # > If so, eliminate overloads that do not have a variadic parameter. + @overload -def variadic(x: int, /) -> str: - ... +def variadic(x: int, /) -> str: ... + @overload -def variadic(x: int, y: int, /, *args: int) -> int: - ... +def variadic(x: int, y: int, /, *args: int) -> int: ... + def variadic(*args: int) -> int | str: return 1 + # > - If this results in only one remaining candidate overload, it is # > the winning match. Evaluate it as if it were a non-overloaded function # > call and stop. + def check_variadic(v: list[int]) -> None: ret1 = variadic(*v) assert_type(ret1, int) -# > Step 5: For each argument, determine whether all possible +# > Step 5: For all arguments, determine whether all possible # > :term:`materializations ` 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. + @overload -def example4(x: list[int], y: int) -> int: - ... +def example4(x: list[int], y: int) -> list[int]: ... + @overload -def example4(x: list[str], y: str) -> int: - ... +def example4(x: list[str], y: str) -> list[int]: ... + @overload -def example4(x: int, y: int) -> list[int]: - ... +def example4(x: int, y: int) -> list[str]: ... + + +def example4(x: list[int] | list[str] | int, y: int | str) -> list[int] | list[str]: + return [] -def example4(x: list[int] | list[str] | int, y: int | str) -> int | list[int]: - return 1 -def check_example4(v1: list[Any], v2: Any): +def check_example4(v1: list[Any], v2: Any) -> None: ret1 = example4(v1, v2) - assert_type(ret1, int) + assert_type(ret1, list[int]) ret2 = example4(v2, 1) assert_type(ret2, Any) + + +@overload +def example5(obj: list[int]) -> list[int]: ... + + +@overload +def example5(obj: list[str]) -> list[str]: ... + + +def example5(obj: Any) -> list[Any]: + return [] + + +def check_example5(b: list[Any]) -> None: + assert_type(example5(b), Any) + + +@overload +def example6(a: int, b: Any) -> float: ... + + +@overload +def example6(a: float, b: T) -> T: ... + + +def example6(a: float, b: T) -> T: ... + + +def check_example6(a: list, b: Any) -> None: + m: list[int] = [] + + v1 = example6(1, a) + assert_type(v1, float) + + v2 = example6(1, b) + assert_type(v2, float) + + v3 = example6(1, m) + assert_type(v3, float) + + v4 = example6(1.0, "") + assert_type(v4, str) + + v5 = example6(1.0, b) + assert_type(v5, Any) + + v6 = example6(1.0, m) + assert_type(v6, list[int]) + + +@overload +def example7(x: list[Any], y: int) -> list[int]: ... + + +@overload +def example7(x: list[Any], y: str) -> list[str]: ... + + +def example7(x: list[Any], y: int | str) -> list[int] | list[str]: + return [] + + +def check_example7(v1: list[Any], v2: Any) -> None: + ret1 = example7(v1, 1) + assert_type(ret1, list[int]) + + ret2 = example7(v1, "") + assert_type(ret2, list[str]) + + ret3 = example7(v1, v2) + assert_type(ret3, Any) From 2c466d49eb653f32858f01d7845067e3a2d13cff Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Tue, 1 Apr 2025 17:11:04 -0700 Subject: [PATCH 2/2] Incorporated feedback from Carl's code review. --- conformance/results/mypy/overloads_evaluation.toml | 10 +++++----- conformance/results/pyre/overloads_evaluation.toml | 6 ++---- conformance/results/pyre/version.toml | 2 +- .../results/pytype/overloads_evaluation.toml | 8 ++++---- conformance/results/pytype/version.toml | 2 +- conformance/results/results.html | 6 +++--- conformance/tests/overloads_evaluation.py | 13 +++++++++++-- 7 files changed, 27 insertions(+), 20 deletions(-) diff --git a/conformance/results/mypy/overloads_evaluation.toml b/conformance/results/mypy/overloads_evaluation.toml index f2899d8b..91b04235 100644 --- a/conformance/results/mypy/overloads_evaluation.toml +++ b/conformance/results/mypy/overloads_evaluation.toml @@ -4,7 +4,7 @@ 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 is some cases where overload is not ambiguous. +Evaluates Any in some cases where overload is not ambiguous. """ conformance_automated = "Fail" errors_diff = """ @@ -16,8 +16,8 @@ Line 204: Unexpected errors ['overloads_evaluation.py:204: error: Argument 1 to Line 205: Unexpected errors ['overloads_evaluation.py:205: error: Expression is of type "int", not "int | str" [assert-type]'] Line 264: Unexpected errors ['overloads_evaluation.py:264: error: Expression is of type "list[Any]", not "Any" [assert-type]'] Line 280: Unexpected errors ['overloads_evaluation.py:280: error: Expression is of type "list[Any]", not "Any" [assert-type]'] -Line 298: Unexpected errors ['overloads_evaluation.py:298: error: Expression is of type "Any", not "float" [assert-type]'] -Line 336: Unexpected errors ['overloads_evaluation.py:336: error: Expression is of type "list[Any]", not "Any" [assert-type]'] +Line 301: Unexpected errors ['overloads_evaluation.py:301: error: Expression is of type "Any", not "float" [assert-type]'] +Line 345: Unexpected errors ['overloads_evaluation.py:345: error: Expression is of type "list[Any]", not "Any" [assert-type]'] """ output = """ overloads_evaluation.py:38: error: All overload variants of "example1_1" require at least one argument [call-overload] @@ -48,6 +48,6 @@ overloads_evaluation.py:204: error: Argument 1 to "expand_tuple" has incompatibl overloads_evaluation.py:205: error: Expression is of type "int", not "int | str" [assert-type] overloads_evaluation.py:264: error: Expression is of type "list[Any]", not "Any" [assert-type] overloads_evaluation.py:280: error: Expression is of type "list[Any]", not "Any" [assert-type] -overloads_evaluation.py:298: error: Expression is of type "Any", not "float" [assert-type] -overloads_evaluation.py:336: error: Expression is of type "list[Any]", not "Any" [assert-type] +overloads_evaluation.py:301: error: Expression is of type "Any", not "float" [assert-type] +overloads_evaluation.py:345: error: Expression is of type "list[Any]", not "Any" [assert-type] """ diff --git a/conformance/results/pyre/overloads_evaluation.toml b/conformance/results/pyre/overloads_evaluation.toml index c70070c2..c5ca3378 100644 --- a/conformance/results/pyre/overloads_evaluation.toml +++ b/conformance/results/pyre/overloads_evaluation.toml @@ -22,8 +22,7 @@ Line 205: Unexpected errors ['overloads_evaluation.py:205:4 Assert type [70]: Ex Line 234: Unexpected errors ['overloads_evaluation.py:234:4 Assert type [70]: Expected `int` but got `str`.'] Line 264: Unexpected errors ['overloads_evaluation.py:264:4 Assert type [70]: Expected `typing.Any` but got `List[int]`.'] Line 280: Unexpected errors ['overloads_evaluation.py:280:4 Assert type [70]: Expected `typing.Any` but got `List[int]`.'] -Line 307: Unexpected errors ["overloads_evaluation.py:307:4 Assert type [70]: Expected `str` but got `typing_extensions.Literal['']`."] -Line 336: Unexpected errors ['overloads_evaluation.py:336:4 Assert type [70]: Expected `typing.Any` but got `List[int]`.'] +Line 345: Unexpected errors ['overloads_evaluation.py:345:4 Assert type [70]: Expected `typing.Any` but got `List[int]`.'] """ output = """ overloads_evaluation.py:38:0 Missing argument [20]: Call `example1_1` expects argument `x`. @@ -44,6 +43,5 @@ overloads_evaluation.py:205:4 Assert type [70]: Expected `Union[int, str]` but g overloads_evaluation.py:234:4 Assert type [70]: Expected `int` but got `str`. overloads_evaluation.py:264:4 Assert type [70]: Expected `typing.Any` but got `List[int]`. overloads_evaluation.py:280:4 Assert type [70]: Expected `typing.Any` but got `List[int]`. -overloads_evaluation.py:307:4 Assert type [70]: Expected `str` but got `typing_extensions.Literal['']`. -overloads_evaluation.py:336:4 Assert type [70]: Expected `typing.Any` but got `List[int]`. +overloads_evaluation.py:345:4 Assert type [70]: Expected `typing.Any` but got `List[int]`. """ diff --git a/conformance/results/pyre/version.toml b/conformance/results/pyre/version.toml index 94de3055..4b79e199 100644 --- a/conformance/results/pyre/version.toml +++ b/conformance/results/pyre/version.toml @@ -1,2 +1,2 @@ version = "pyre 0.9.23" -test_duration = 7.3 +test_duration = 6.4 diff --git a/conformance/results/pytype/overloads_evaluation.toml b/conformance/results/pytype/overloads_evaluation.toml index 94f4f97c..6efdfacc 100644 --- a/conformance/results/pytype/overloads_evaluation.toml +++ b/conformance/results/pytype/overloads_evaluation.toml @@ -26,7 +26,7 @@ Line 234: Unexpected errors ['overloads_evaluation.py:234:5: \\x1b[1m\\x1b[31mer Line 264: Unexpected errors ['overloads_evaluation.py:264:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_example4: list[int] [assert-type]'] Line 280: Unexpected errors ['overloads_evaluation.py:280:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_example5: list[int] [assert-type]'] Line 291: Unexpected errors ['overloads_evaluation.py:291:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in example6: bad return type [bad-return-type]', 'overloads_evaluation.py:291:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in example6: bad return type [bad-return-type]', 'overloads_evaluation.py:291:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in example6: bad return type [bad-return-type]'] -Line 336: Unexpected errors ['overloads_evaluation.py:336:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_example7: list[int] [assert-type]'] +Line 345: Unexpected errors ['overloads_evaluation.py:345:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in check_example7: list[int] [assert-type]'] """ output = """ overloads_evaluation.py:33:12: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in example1_1: bad return type [bad-return-type] @@ -152,20 +152,20 @@ def example6(a: float, b: T) -> T: ... \u001b[1m\u001b[31m\u001b[39m\u001b[0m Called from (traceback): - line 312, in check_example6 + line 321, in check_example6 overloads_evaluation.py:291:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in example6: bad return type [bad-return-type] def example6(a: float, b: T) -> T: ... \u001b[1m\u001b[31m\u001b[39m\u001b[0m Called from (traceback): - line 306, in check_example6 + line 315, in check_example6 overloads_evaluation.py:291:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in example6: bad return type [bad-return-type] def example6(a: float, b: T) -> T: ... \u001b[1m\u001b[31m\u001b[39m\u001b[0m -overloads_evaluation.py:336:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_example7: list[int] [assert-type] +overloads_evaluation.py:345:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in check_example7: list[int] [assert-type] assert_type(ret3, Any) \u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m diff --git a/conformance/results/pytype/version.toml b/conformance/results/pytype/version.toml index ec1b4602..6b337433 100644 --- a/conformance/results/pytype/version.toml +++ b/conformance/results/pytype/version.toml @@ -1,2 +1,2 @@ version = "pytype 2024.10.11" -test_duration = 33.4 +test_duration = 32.7 diff --git a/conformance/results/results.html b/conformance/results/results.html index 954bf6b7..0429a3c4 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -165,10 +165,10 @@

Python Type System Conformance Test Results

1.3sec
pyre 0.9.23
-
7.3sec
+
6.4sec
pytype 2024.10.11
-
33.4sec
+
32.7sec
@@ -691,7 +691,7 @@

Python Type System Conformance Test Results

Fail

Does not enforce any of the specified rules regarding overload definitions.

     overloads_evaluation -
Partial

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 is some cases where overload is not ambiguous.

+
Partial

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.

Partial

Does not evaluate Any in some cases where overload is ambiguous.

Partial

Does not expand boolean arguments to Literal[True] and Literal[False].

Does not expand enum arguments to literal variants.

Does not expand type[A | B] to type[A] and type[B].

Does not expand tuple arguments to possible combinations.

Does not prefer variadic match to indeterminate-length unpacked argument.

Does not treat multiple matches due to gradual types as ambiguous.

Partial

Does not perform argument expansion (on any types) when matching overloads.

Does not treat multiple matches due to gradual types as ambiguous.

Does not prefer variadic match to indeterminate-length unpacked argument.

diff --git a/conformance/tests/overloads_evaluation.py b/conformance/tests/overloads_evaluation.py index 4d1ff18d..094b177e 100644 --- a/conformance/tests/overloads_evaluation.py +++ b/conformance/tests/overloads_evaluation.py @@ -291,19 +291,28 @@ def example6(a: float, b: T) -> T: ... def example6(a: float, b: T) -> T: ... -def check_example6(a: list, b: Any) -> None: +def check_example6(a: list[Any], b: Any, c: str) -> None: m: list[int] = [] + # All possible materializations of list[Any] are + # assignable to Any, so this matches the first overload + # and eliminates all subsequent overloads. v1 = example6(1, a) assert_type(v1, float) + # All possible materializations of Any are + # assignable to Any, so this matches the first overload + # and eliminates all subsequent overloads. v2 = example6(1, b) assert_type(v2, float) + # All possible materializations of list[int] are + # assignable to Any, so this matches the first overload + # and eliminates all subsequent overloads. v3 = example6(1, m) assert_type(v3, float) - v4 = example6(1.0, "") + v4 = example6(1.0, c) assert_type(v4, str) v5 = example6(1.0, b)