From c9776dc74a5b70603d0a506c6cdba15d66d1bf8a Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Sun, 5 May 2024 20:22:40 -0700 Subject: [PATCH] Added new conformance test to go along with the recently-accepted new sections in the "Callables" chapter of the typing spec. --- .../results/mypy/callables_annotation.toml | 48 ++- .../results/mypy/callables_subtyping.toml | 179 +++++++++++ .../results/pyre/callables_annotation.toml | 57 +++- .../results/pyre/callables_subtyping.toml | 59 ++++ conformance/results/pyre/version.toml | 2 +- .../results/pyright/callables_annotation.toml | 61 +++- .../results/pyright/callables_subtyping.toml | 193 ++++++++++++ .../results/pytype/callables_annotation.toml | 38 ++- .../results/pytype/callables_subtyping.toml | 50 +++ conformance/results/pytype/version.toml | 2 +- conformance/results/results.html | 18 +- conformance/tests/callables_annotation.py | 133 +++++++- conformance/tests/callables_subtyping.py | 297 ++++++++++++++++++ 13 files changed, 1071 insertions(+), 66 deletions(-) create mode 100644 conformance/results/mypy/callables_subtyping.toml create mode 100644 conformance/results/pyre/callables_subtyping.toml create mode 100644 conformance/results/pyright/callables_subtyping.toml create mode 100644 conformance/results/pytype/callables_subtyping.toml create mode 100644 conformance/tests/callables_subtyping.py diff --git a/conformance/results/mypy/callables_annotation.toml b/conformance/results/mypy/callables_annotation.toml index 6e9be33ee..c018feb9f 100644 --- a/conformance/results/mypy/callables_annotation.toml +++ b/conformance/results/mypy/callables_annotation.toml @@ -1,19 +1,37 @@ -conformant = "Pass" +conformant = "Partial" +notes = """ +Incorrectly treats "*args: T, **kwargs: T" as "..." when T is specialized to Any. +Does not treat "*args: Any, **kargs: Any" as "..." when separated by keyword parameter. +""" output = """ -callables_annotation.py:13: error: Too few arguments [call-arg] -callables_annotation.py:14: error: Argument 2 has incompatible type "int"; expected "str" [arg-type] -callables_annotation.py:15: error: Too many arguments [call-arg] -callables_annotation.py:17: error: Unexpected keyword argument "a" [call-arg] -callables_annotation.py:17: error: Unexpected keyword argument "b" [call-arg] -callables_annotation.py:23: error: Too many arguments [call-arg] -callables_annotation.py:40: error: Please use "Callable[[], ]" or "Callable" [misc] -callables_annotation.py:41: error: The first argument to Callable must be a list of types, parameter specification, or "..." [valid-type] -callables_annotation.py:41: note: See https://mypy.readthedocs.io/en/stable/kinds_of_types.html#callable-types-and-lambdas -callables_annotation.py:42: error: Bracketed expression "[...]" is not valid as a type [valid-type] -callables_annotation.py:42: note: Did you mean "List[...]"? -callables_annotation.py:43: error: Please use "Callable[[], ]" or "Callable" [misc] -callables_annotation.py:44: error: Unexpected "..." [misc] +callables_annotation.py:25: error: Too few arguments [call-arg] +callables_annotation.py:26: error: Argument 2 has incompatible type "int"; expected "str" [arg-type] +callables_annotation.py:27: error: Too many arguments [call-arg] +callables_annotation.py:29: error: Unexpected keyword argument "a" [call-arg] +callables_annotation.py:29: error: Unexpected keyword argument "b" [call-arg] +callables_annotation.py:35: error: Too many arguments [call-arg] +callables_annotation.py:55: error: Please use "Callable[[], ]" or "Callable" [misc] +callables_annotation.py:56: error: The first argument to Callable must be a list of types, parameter specification, or "..." [valid-type] +callables_annotation.py:56: note: See https://mypy.readthedocs.io/en/stable/kinds_of_types.html#callable-types-and-lambdas +callables_annotation.py:57: error: Bracketed expression "[...]" is not valid as a type [valid-type] +callables_annotation.py:57: note: Did you mean "List[...]"? +callables_annotation.py:58: error: Please use "Callable[[], ]" or "Callable" [misc] +callables_annotation.py:59: error: Unexpected "..." [misc] +callables_annotation.py:91: error: Incompatible types in assignment (expression has type "Callable[[], str]", variable has type "Callable[[int, VarArg(Any), KwArg(Any)], str]") [assignment] +callables_annotation.py:93: error: Incompatible types in assignment (expression has type "Callable[[NamedArg(int, 'a')], str]", variable has type "Callable[[int, VarArg(Any), KwArg(Any)], str]") [assignment] +callables_annotation.py:136: error: Expression is of type "Proto3", not "Callable[..., None]" [assert-type] +callables_annotation.py:139: error: Incompatible types in assignment (expression has type "Proto7", variable has type "Proto6") [assignment] +callables_annotation.py:139: note: Following member(s) of "Proto7" have conflicts: +callables_annotation.py:139: note: Expected: +callables_annotation.py:139: note: def __call__(self, int, /, *args: Any, k: str, **kwargs: Any) -> None +callables_annotation.py:139: note: Got: +callables_annotation.py:139: note: def __call__(self, float, /, b: int, *, k: str, m: str) -> None +callables_annotation.py:152: error: Incompatible types in assignment (expression has type "Callable[[], str]", variable has type "Callable[[int, VarArg(Any), KwArg(Any)], str]") [assignment] +callables_annotation.py:167: error: Incompatible types in assignment (expression has type "Callable[[int, str], str]", variable has type "Callable[[str, VarArg(Any), KwArg(Any)], str]") [assignment] +callables_annotation.py:169: error: Incompatible types in assignment (expression has type "Callable[[int, str], str]", variable has type "Callable[[str, VarArg(Any), KwArg(Any)], str]") [assignment] """ -conformance_automated = "Pass" +conformance_automated = "Fail" errors_diff = """ +Line 134: Expected 1 errors +Line 139: Unexpected errors ['callables_annotation.py:139: error: Incompatible types in assignment (expression has type "Proto7", variable has type "Proto6") [assignment]'] """ diff --git a/conformance/results/mypy/callables_subtyping.toml b/conformance/results/mypy/callables_subtyping.toml new file mode 100644 index 000000000..3dfcb382f --- /dev/null +++ b/conformance/results/mypy/callables_subtyping.toml @@ -0,0 +1,179 @@ +conformant = "Pass" +errors_diff = """ +""" +output = """ +callables_subtyping.py:26: error: Incompatible types in assignment (expression has type "Callable[[int], int]", variable has type "Callable[[float], float]") [assignment] +callables_subtyping.py:29: error: Incompatible types in assignment (expression has type "Callable[[float], float]", variable has type "Callable[[int], int]") [assignment] +callables_subtyping.py:51: error: Incompatible types in assignment (expression has type "PosOnly2", variable has type "Standard2") [assignment] +callables_subtyping.py:52: error: Incompatible types in assignment (expression has type "KwOnly2", variable has type "Standard2") [assignment] +callables_subtyping.py:52: note: Following member(s) of "KwOnly2" have conflicts: +callables_subtyping.py:52: note: Expected: +callables_subtyping.py:52: note: def __call__(self, a: int, b: int) -> None +callables_subtyping.py:52: note: Got: +callables_subtyping.py:52: note: def __call__(self, *, b: int, a: int) -> None +callables_subtyping.py:55: error: Incompatible types in assignment (expression has type "KwOnly2", variable has type "PosOnly2") [assignment] +callables_subtyping.py:55: note: Following member(s) of "KwOnly2" have conflicts: +callables_subtyping.py:55: note: Expected: +callables_subtyping.py:55: note: def __call__(self, int, int, /) -> None +callables_subtyping.py:55: note: Got: +callables_subtyping.py:55: note: def __call__(self, *, b: int, a: int) -> None +callables_subtyping.py:58: error: Incompatible types in assignment (expression has type "PosOnly2", variable has type "KwOnly2") [assignment] +callables_subtyping.py:58: note: Following member(s) of "PosOnly2" have conflicts: +callables_subtyping.py:58: note: Expected: +callables_subtyping.py:58: note: def __call__(self, *, b: int, a: int) -> None +callables_subtyping.py:58: note: Got: +callables_subtyping.py:58: note: def __call__(self, int, int, /) -> None +callables_subtyping.py:82: error: Incompatible types in assignment (expression has type "NoArgs3", variable has type "IntArgs3") [assignment] +callables_subtyping.py:82: note: Following member(s) of "NoArgs3" have conflicts: +callables_subtyping.py:82: note: Expected: +callables_subtyping.py:82: note: def __call__(self, *args: int) -> None +callables_subtyping.py:82: note: Got: +callables_subtyping.py:82: note: def __call__(self) -> None +callables_subtyping.py:85: error: Incompatible types in assignment (expression has type "NoArgs3", variable has type "FloatArgs3") [assignment] +callables_subtyping.py:85: note: Following member(s) of "NoArgs3" have conflicts: +callables_subtyping.py:85: note: Expected: +callables_subtyping.py:85: note: def __call__(self, *args: float) -> None +callables_subtyping.py:85: note: Got: +callables_subtyping.py:85: note: def __call__(self) -> None +callables_subtyping.py:86: error: Incompatible types in assignment (expression has type "IntArgs3", variable has type "FloatArgs3") [assignment] +callables_subtyping.py:86: note: Following member(s) of "IntArgs3" have conflicts: +callables_subtyping.py:86: note: Expected: +callables_subtyping.py:86: note: def __call__(self, *args: float) -> None +callables_subtyping.py:86: note: Got: +callables_subtyping.py:86: note: def __call__(self, *args: int) -> None +callables_subtyping.py:116: error: Incompatible types in assignment (expression has type "IntArgs4", variable has type "PosOnly4") [assignment] +callables_subtyping.py:116: note: Following member(s) of "IntArgs4" have conflicts: +callables_subtyping.py:116: note: Expected: +callables_subtyping.py:116: note: def __call__(self, int, str, /) -> None +callables_subtyping.py:116: note: Got: +callables_subtyping.py:116: note: def __call__(self, *args: int) -> None +callables_subtyping.py:119: error: Incompatible types in assignment (expression has type "StrArgs4", variable has type "IntStrArgs4") [assignment] +callables_subtyping.py:119: note: Following member(s) of "StrArgs4" have conflicts: +callables_subtyping.py:119: note: Expected: +callables_subtyping.py:119: note: def __call__(self, *args: int | str) -> None +callables_subtyping.py:119: note: Got: +callables_subtyping.py:119: note: def __call__(self, int, /, *args: str) -> None +callables_subtyping.py:120: error: Incompatible types in assignment (expression has type "IntArgs4", variable has type "IntStrArgs4") [assignment] +callables_subtyping.py:120: note: Following member(s) of "IntArgs4" have conflicts: +callables_subtyping.py:120: note: Expected: +callables_subtyping.py:120: note: def __call__(self, *args: int | str) -> None +callables_subtyping.py:120: note: Got: +callables_subtyping.py:120: note: def __call__(self, *args: int) -> None +callables_subtyping.py:122: error: Incompatible types in assignment (expression has type "IntArgs4", variable has type "StrArgs4") [assignment] +callables_subtyping.py:122: note: Following member(s) of "IntArgs4" have conflicts: +callables_subtyping.py:122: note: Expected: +callables_subtyping.py:122: note: def __call__(self, int, /, *args: str) -> None +callables_subtyping.py:122: note: Got: +callables_subtyping.py:122: note: def __call__(self, *args: int) -> None +callables_subtyping.py:124: error: Incompatible types in assignment (expression has type "StrArgs4", variable has type "IntArgs4") [assignment] +callables_subtyping.py:124: note: Following member(s) of "StrArgs4" have conflicts: +callables_subtyping.py:124: note: Expected: +callables_subtyping.py:124: note: def __call__(self, *args: int) -> None +callables_subtyping.py:124: note: Got: +callables_subtyping.py:124: note: def __call__(self, int, /, *args: str) -> None +callables_subtyping.py:125: error: Incompatible types in assignment (expression has type "IntStrArgs4", variable has type "Standard4") [assignment] +callables_subtyping.py:126: error: Incompatible types in assignment (expression has type "StrArgs4", variable has type "Standard4") [assignment] +callables_subtyping.py:151: error: Incompatible types in assignment (expression has type "NoKwargs5", variable has type "IntKwargs5") [assignment] +callables_subtyping.py:151: note: Following member(s) of "NoKwargs5" have conflicts: +callables_subtyping.py:151: note: Expected: +callables_subtyping.py:151: note: def __call__(self, **kwargs: int) -> None +callables_subtyping.py:151: note: Got: +callables_subtyping.py:151: note: def __call__(self) -> None +callables_subtyping.py:154: error: Incompatible types in assignment (expression has type "NoKwargs5", variable has type "FloatKwargs5") [assignment] +callables_subtyping.py:154: note: Following member(s) of "NoKwargs5" have conflicts: +callables_subtyping.py:154: note: Expected: +callables_subtyping.py:154: note: def __call__(self, **kwargs: float) -> None +callables_subtyping.py:154: note: Got: +callables_subtyping.py:154: note: def __call__(self) -> None +callables_subtyping.py:155: error: Incompatible types in assignment (expression has type "IntKwargs5", variable has type "FloatKwargs5") [assignment] +callables_subtyping.py:155: note: Following member(s) of "IntKwargs5" have conflicts: +callables_subtyping.py:155: note: Expected: +callables_subtyping.py:155: note: def __call__(self, **kwargs: float) -> None +callables_subtyping.py:155: note: Got: +callables_subtyping.py:155: note: def __call__(self, **kwargs: int) -> None +callables_subtyping.py:187: error: Incompatible types in assignment (expression has type "IntKwargs6", variable has type "KwOnly6") [assignment] +callables_subtyping.py:187: note: Following member(s) of "IntKwargs6" have conflicts: +callables_subtyping.py:187: note: Expected: +callables_subtyping.py:187: note: def __call__(self, *, a: int, b: str) -> None +callables_subtyping.py:187: note: Got: +callables_subtyping.py:187: note: def __call__(self, **kwargs: int) -> None +callables_subtyping.py:190: error: Incompatible types in assignment (expression has type "StrKwargs6", variable has type "IntStrKwargs6") [assignment] +callables_subtyping.py:190: note: Following member(s) of "StrKwargs6" have conflicts: +callables_subtyping.py:190: note: Expected: +callables_subtyping.py:190: note: def __call__(self, **kwargs: int | str) -> None +callables_subtyping.py:190: note: Got: +callables_subtyping.py:190: note: def __call__(self, *, a: int, **kwargs: str) -> None +callables_subtyping.py:191: error: Incompatible types in assignment (expression has type "IntKwargs6", variable has type "IntStrKwargs6") [assignment] +callables_subtyping.py:191: note: Following member(s) of "IntKwargs6" have conflicts: +callables_subtyping.py:191: note: Expected: +callables_subtyping.py:191: note: def __call__(self, **kwargs: int | str) -> None +callables_subtyping.py:191: note: Got: +callables_subtyping.py:191: note: def __call__(self, **kwargs: int) -> None +callables_subtyping.py:193: error: Incompatible types in assignment (expression has type "IntKwargs6", variable has type "StrKwargs6") [assignment] +callables_subtyping.py:193: note: Following member(s) of "IntKwargs6" have conflicts: +callables_subtyping.py:193: note: Expected: +callables_subtyping.py:193: note: def __call__(self, *, a: int, **kwargs: str) -> None +callables_subtyping.py:193: note: Got: +callables_subtyping.py:193: note: def __call__(self, **kwargs: int) -> None +callables_subtyping.py:195: error: Incompatible types in assignment (expression has type "StrKwargs6", variable has type "IntKwargs6") [assignment] +callables_subtyping.py:195: note: Following member(s) of "StrKwargs6" have conflicts: +callables_subtyping.py:195: note: Expected: +callables_subtyping.py:195: note: def __call__(self, **kwargs: int) -> None +callables_subtyping.py:195: note: Got: +callables_subtyping.py:195: note: def __call__(self, *, a: int, **kwargs: str) -> None +callables_subtyping.py:196: error: Incompatible types in assignment (expression has type "IntStrKwargs6", variable has type "Standard6") [assignment] +callables_subtyping.py:196: note: Following member(s) of "IntStrKwargs6" have conflicts: +callables_subtyping.py:196: note: Expected: +callables_subtyping.py:196: note: def __call__(self, a: int, b: str) -> None +callables_subtyping.py:196: note: Got: +callables_subtyping.py:196: note: def __call__(self, **kwargs: int | str) -> None +callables_subtyping.py:197: error: Incompatible types in assignment (expression has type "StrKwargs6", variable has type "Standard6") [assignment] +callables_subtyping.py:197: note: Following member(s) of "StrKwargs6" have conflicts: +callables_subtyping.py:197: note: Expected: +callables_subtyping.py:197: note: def __call__(self, a: int, b: str) -> None +callables_subtyping.py:197: note: Got: +callables_subtyping.py:197: note: def __call__(self, *, a: int, **kwargs: str) -> None +callables_subtyping.py:236: error: Incompatible types in assignment (expression has type "NoDefaultArg8", variable has type "DefaultArg8") [assignment] +callables_subtyping.py:236: note: Following member(s) of "NoDefaultArg8" have conflicts: +callables_subtyping.py:236: note: Expected: +callables_subtyping.py:236: note: def __call__(self, x: int = ...) -> None +callables_subtyping.py:236: note: Got: +callables_subtyping.py:236: note: def __call__(self, x: int) -> None +callables_subtyping.py:237: error: Incompatible types in assignment (expression has type "NoX8", variable has type "DefaultArg8") [assignment] +callables_subtyping.py:237: note: Following member(s) of "NoX8" have conflicts: +callables_subtyping.py:237: note: Expected: +callables_subtyping.py:237: note: def __call__(self, x: int = ...) -> None +callables_subtyping.py:237: note: Got: +callables_subtyping.py:237: note: def __call__(self) -> None +callables_subtyping.py:240: error: Incompatible types in assignment (expression has type "NoX8", variable has type "NoDefaultArg8") [assignment] +callables_subtyping.py:240: note: Following member(s) of "NoX8" have conflicts: +callables_subtyping.py:240: note: Expected: +callables_subtyping.py:240: note: def __call__(self, x: int) -> None +callables_subtyping.py:240: note: Got: +callables_subtyping.py:240: note: def __call__(self) -> None +callables_subtyping.py:243: error: Incompatible types in assignment (expression has type "NoDefaultArg8", variable has type "NoX8") [assignment] +callables_subtyping.py:243: note: Following member(s) of "NoDefaultArg8" have conflicts: +callables_subtyping.py:243: note: Expected: +callables_subtyping.py:243: note: def __call__(self) -> None +callables_subtyping.py:243: note: Got: +callables_subtyping.py:243: note: def __call__(self, x: int) -> None +callables_subtyping.py:273: error: Incompatible types in assignment (expression has type "Overloaded9", variable has type "FloatArg9") [assignment] +callables_subtyping.py:273: note: Following member(s) of "Overloaded9" have conflicts: +callables_subtyping.py:273: note: Expected: +callables_subtyping.py:273: note: def __call__(self, x: float) -> float +callables_subtyping.py:273: note: Got: +callables_subtyping.py:273: note: @overload +callables_subtyping.py:273: note: def __call__(self, x: int) -> int +callables_subtyping.py:273: note: @overload +callables_subtyping.py:273: note: def __call__(self, x: str) -> str +callables_subtyping.py:297: error: Incompatible types in assignment (expression has type "StrArg10", variable has type "Overloaded10") [assignment] +callables_subtyping.py:297: note: Following member(s) of "StrArg10" have conflicts: +callables_subtyping.py:297: note: Expected: +callables_subtyping.py:297: note: @overload +callables_subtyping.py:297: note: def __call__(self, x: int, y: str) -> float +callables_subtyping.py:297: note: @overload +callables_subtyping.py:297: note: def __call__(self, x: str) -> complex +callables_subtyping.py:297: note: Got: +callables_subtyping.py:297: note: def __call__(self, x: str) -> complex +""" +conformance_automated = "Pass" diff --git a/conformance/results/pyre/callables_annotation.toml b/conformance/results/pyre/callables_annotation.toml index a4ef0fe68..38d105cc4 100644 --- a/conformance/results/pyre/callables_annotation.toml +++ b/conformance/results/pyre/callables_annotation.toml @@ -2,21 +2,54 @@ conformant = "Partial" notes = """ Does not evaluate correct type for `*args: int` parameter. Does not reject illegal form `Callable[[...], int]`. +Does not correctly implement type compatibility rules for "...". +Does not treat "*args: Any, **kwargs: Any" as "...". """ output = """ -callables_annotation.py:13:4 Missing argument [20]: PositionalOnly call expects argument in position 1. -callables_annotation.py:14:10 Incompatible parameter type [6]: In anonymous call, for 2nd positional argument, expected `str` but got `int`. -callables_annotation.py:15:4 Too many arguments [19]: PositionalOnly call expects 2 positional arguments, 3 were provided. -callables_annotation.py:17:4 Unexpected keyword [28]: Unexpected keyword argument `a` to anonymous call. -callables_annotation.py:23:4 Too many arguments [19]: PositionalOnly call expects 0 positional arguments, 1 was provided. -callables_annotation.py:36:28 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `Tuple[Type[int], typing.Any]`. -callables_annotation.py:40:4 Invalid type [31]: Expression `typing.Callable[int]` is not a valid type. -callables_annotation.py:41:4 Invalid type [31]: Expression `typing.Callable[(int, int)]` is not a valid type. -callables_annotation.py:42:4 Invalid type [31]: Expression `typing.Callable[([], [int])]` is not a valid type. -callables_annotation.py:43:4 Invalid type [31]: Expression `typing.Callable[(int, int, int)]` is not a valid type. +callables_annotation.py:25:4 Missing argument [20]: PositionalOnly call expects argument in position 1. +callables_annotation.py:26:10 Incompatible parameter type [6]: In anonymous call, for 2nd positional argument, expected `str` but got `int`. +callables_annotation.py:27:4 Too many arguments [19]: PositionalOnly call expects 2 positional arguments, 3 were provided. +callables_annotation.py:29:4 Unexpected keyword [28]: Unexpected keyword argument `a` to anonymous call. +callables_annotation.py:35:4 Too many arguments [19]: PositionalOnly call expects 0 positional arguments, 1 was provided. +callables_annotation.py:51:28 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `Tuple[Type[int], typing.Any]`. +callables_annotation.py:55:4 Invalid type [31]: Expression `typing.Callable[int]` is not a valid type. +callables_annotation.py:56:4 Invalid type [31]: Expression `typing.Callable[(int, int)]` is not a valid type. +callables_annotation.py:57:4 Invalid type [31]: Expression `typing.Callable[([], [int])]` is not a valid type. +callables_annotation.py:58:4 Invalid type [31]: Expression `typing.Callable[(int, int, int)]` is not a valid type. +callables_annotation.py:89:5 Invalid type [31]: Expression `typing.Callable[(typing.Concatenate[(int, ...)], str)]` is not a valid type. +callables_annotation.py:133:29 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[typing.Any, None]`. +callables_annotation.py:134:20 Undefined attribute [16]: `Proto5` has no attribute `__getitem__`. +callables_annotation.py:135:29 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[object, None]`. +callables_annotation.py:136:29 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[typing.Any, None]`. +callables_annotation.py:137:20 Undefined attribute [16]: `Proto4` has no attribute `__getitem__`. +callables_annotation.py:139:4 Incompatible variable type [9]: f1 is declared to have type `Proto6` but is used as type `Proto7`. +callables_annotation.py:146:0 Incompatible variable type [9]: Callback1 is declared to have type `TypeAlias` but is used as type `Type[typing.Callable[..., str]]`. +callables_annotation.py:147:0 Incompatible variable type [9]: Callback2 is declared to have type `TypeAlias` but is used as type `Type[typing.Callable[..., str]]`. +callables_annotation.py:151:8 Undefined or invalid type [11]: Annotation `Callback1` is not defined as a type. +callables_annotation.py:152:8 Undefined or invalid type [11]: Annotation `Callback2` is not defined as a type. +callables_annotation.py:161:0 Incompatible variable type [9]: CallbackWithInt is declared to have type `TypeAlias` but is used as type `Type[typing.Callable[..., str]]`. +callables_annotation.py:162:0 Incompatible variable type [9]: CallbackWithStr is declared to have type `TypeAlias` but is used as type `Type[typing.Callable[..., str]]`. +callables_annotation.py:166:8 Invalid type [31]: Expression `typing.Callable[(typing.Concatenate[(int, ...)], str)]` is not a valid type. +callables_annotation.py:167:8 Invalid type [31]: Expression `typing.Callable[(typing.Concatenate[(str, ...)], str)]` is not a valid type. +callables_annotation.py:168:8 Undefined or invalid type [11]: Annotation `CallbackWithInt` is not defined as a type. +callables_annotation.py:169:8 Undefined or invalid type [11]: Annotation `CallbackWithStr` is not defined as a type. """ conformance_automated = "Fail" errors_diff = """ -Line 44: Expected 1 errors -Line 36: Unexpected errors ['callables_annotation.py:36:28 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `Tuple[Type[int], typing.Any]`.'] +Line 59: Expected 1 errors +Line 91: Expected 1 errors +Line 93: Expected 1 errors +Line 51: Unexpected errors ['callables_annotation.py:51:28 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `Tuple[Type[int], typing.Any]`.'] +Line 89: Unexpected errors ['callables_annotation.py:89:5 Invalid type [31]: Expression `typing.Callable[(typing.Concatenate[(int, ...)], str)]` is not a valid type.'] +Line 133: Unexpected errors ['callables_annotation.py:133:29 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[typing.Any, None]`.'] +Line 135: Unexpected errors ['callables_annotation.py:135:29 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[object, None]`.'] +Line 137: Unexpected errors ['callables_annotation.py:137:20 Undefined attribute [16]: `Proto4` has no attribute `__getitem__`.'] +Line 139: Unexpected errors ['callables_annotation.py:139:4 Incompatible variable type [9]: f1 is declared to have type `Proto6` but is used as type `Proto7`.'] +Line 146: Unexpected errors ['callables_annotation.py:146:0 Incompatible variable type [9]: Callback1 is declared to have type `TypeAlias` but is used as type `Type[typing.Callable[..., str]]`.'] +Line 147: Unexpected errors ['callables_annotation.py:147:0 Incompatible variable type [9]: Callback2 is declared to have type `TypeAlias` but is used as type `Type[typing.Callable[..., str]]`.'] +Line 151: Unexpected errors ['callables_annotation.py:151:8 Undefined or invalid type [11]: Annotation `Callback1` is not defined as a type.'] +Line 161: Unexpected errors ['callables_annotation.py:161:0 Incompatible variable type [9]: CallbackWithInt is declared to have type `TypeAlias` but is used as type `Type[typing.Callable[..., str]]`.'] +Line 162: Unexpected errors ['callables_annotation.py:162:0 Incompatible variable type [9]: CallbackWithStr is declared to have type `TypeAlias` but is used as type `Type[typing.Callable[..., str]]`.'] +Line 166: Unexpected errors ['callables_annotation.py:166:8 Invalid type [31]: Expression `typing.Callable[(typing.Concatenate[(int, ...)], str)]` is not a valid type.'] +Line 168: Unexpected errors ['callables_annotation.py:168:8 Undefined or invalid type [11]: Annotation `CallbackWithInt` is not defined as a type.'] """ diff --git a/conformance/results/pyre/callables_subtyping.toml b/conformance/results/pyre/callables_subtyping.toml new file mode 100644 index 000000000..4c686d89e --- /dev/null +++ b/conformance/results/pyre/callables_subtyping.toml @@ -0,0 +1,59 @@ +conformant = "Partial" +notes = """ +Rejects standard parameter as incompatible with keyword-only parameter. +Rejects use of Callable with ParamSpec in TypeAlias definition. +""" +errors_diff = """ +Line 236: Expected 1 errors +Line 57: Unexpected errors ['callables_subtyping.py:57:4 Incompatible variable type [9]: f5 is declared to have type `KwOnly2` but is used as type `Standard2`.'] +Line 188: Unexpected errors ['callables_subtyping.py:188:4 Incompatible variable type [9]: f2 is declared to have type `KwOnly6` but is used as type `IntStrKwargs6`.'] +Line 189: Unexpected errors ['callables_subtyping.py:189:4 Incompatible variable type [9]: f3 is declared to have type `KwOnly6` but is used as type `StrKwargs6`.'] +Line 192: Unexpected errors ['callables_subtyping.py:192:4 Incompatible variable type [9]: f6 is declared to have type `StrKwargs6` but is used as type `IntStrKwargs6`.'] +Line 208: Unexpected errors ['callables_subtyping.py:208:0 Incompatible variable type [9]: TypeAliasWithP is declared to have type `TypeAlias` but is used as type `Type[typing.Callable[..., Variable[$synthetic_attribute_resolution_variable]]]`.', 'callables_subtyping.py:208:37 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[ParamSpec, None]`.'] +Line 211: Unexpected errors ['callables_subtyping.py:211:39 Undefined or invalid type [11]: Annotation `TypeAliasWithP` is not defined as a type.'] +Line 253: Unexpected errors ['callables_subtyping.py:253:4 Missing overload implementation [42]: Overloaded function `Overloaded9.__call__` must have an implementation.'] +Line 282: Unexpected errors ['callables_subtyping.py:282:4 Missing overload implementation [42]: Overloaded function `Overloaded10.__call__` must have an implementation.'] +""" +output = """ +callables_subtyping.py:26:4 Incompatible variable type [9]: f6 is declared to have type `typing.Callable[[float], float]` but is used as type `typing.Callable[[int], int]`. +callables_subtyping.py:29:4 Incompatible variable type [9]: f8 is declared to have type `typing.Callable[[int], int]` but is used as type `typing.Callable[[float], float]`. +callables_subtyping.py:51:4 Incompatible variable type [9]: f1 is declared to have type `Standard2` but is used as type `PosOnly2`. +callables_subtyping.py:52:4 Incompatible variable type [9]: f2 is declared to have type `Standard2` but is used as type `KwOnly2`. +callables_subtyping.py:55:4 Incompatible variable type [9]: f4 is declared to have type `PosOnly2` but is used as type `KwOnly2`. +callables_subtyping.py:57:4 Incompatible variable type [9]: f5 is declared to have type `KwOnly2` but is used as type `Standard2`. +callables_subtyping.py:58:4 Incompatible variable type [9]: f6 is declared to have type `KwOnly2` but is used as type `PosOnly2`. +callables_subtyping.py:82:4 Incompatible variable type [9]: f3 is declared to have type `IntArgs3` but is used as type `NoArgs3`. +callables_subtyping.py:85:4 Incompatible variable type [9]: f5 is declared to have type `FloatArgs3` but is used as type `NoArgs3`. +callables_subtyping.py:86:4 Incompatible variable type [9]: f6 is declared to have type `FloatArgs3` but is used as type `IntArgs3`. +callables_subtyping.py:116:4 Incompatible variable type [9]: f1 is declared to have type `PosOnly4` but is used as type `IntArgs4`. +callables_subtyping.py:119:4 Incompatible variable type [9]: f4 is declared to have type `IntStrArgs4` but is used as type `StrArgs4`. +callables_subtyping.py:120:4 Incompatible variable type [9]: f5 is declared to have type `IntStrArgs4` but is used as type `IntArgs4`. +callables_subtyping.py:122:4 Incompatible variable type [9]: f7 is declared to have type `StrArgs4` but is used as type `IntArgs4`. +callables_subtyping.py:124:4 Incompatible variable type [9]: f9 is declared to have type `IntArgs4` but is used as type `StrArgs4`. +callables_subtyping.py:125:4 Incompatible variable type [9]: f10 is declared to have type `Standard4` but is used as type `IntStrArgs4`. +callables_subtyping.py:126:4 Incompatible variable type [9]: f11 is declared to have type `Standard4` but is used as type `StrArgs4`. +callables_subtyping.py:151:4 Incompatible variable type [9]: f3 is declared to have type `IntKwargs5` but is used as type `NoKwargs5`. +callables_subtyping.py:154:4 Incompatible variable type [9]: f5 is declared to have type `FloatKwargs5` but is used as type `NoKwargs5`. +callables_subtyping.py:155:4 Incompatible variable type [9]: f6 is declared to have type `FloatKwargs5` but is used as type `IntKwargs5`. +callables_subtyping.py:187:4 Incompatible variable type [9]: f1 is declared to have type `KwOnly6` but is used as type `IntKwargs6`. +callables_subtyping.py:188:4 Incompatible variable type [9]: f2 is declared to have type `KwOnly6` but is used as type `IntStrKwargs6`. +callables_subtyping.py:189:4 Incompatible variable type [9]: f3 is declared to have type `KwOnly6` but is used as type `StrKwargs6`. +callables_subtyping.py:190:4 Incompatible variable type [9]: f4 is declared to have type `IntStrKwargs6` but is used as type `StrKwargs6`. +callables_subtyping.py:191:4 Incompatible variable type [9]: f5 is declared to have type `IntStrKwargs6` but is used as type `IntKwargs6`. +callables_subtyping.py:192:4 Incompatible variable type [9]: f6 is declared to have type `StrKwargs6` but is used as type `IntStrKwargs6`. +callables_subtyping.py:193:4 Incompatible variable type [9]: f7 is declared to have type `StrKwargs6` but is used as type `IntKwargs6`. +callables_subtyping.py:195:4 Incompatible variable type [9]: f9 is declared to have type `IntKwargs6` but is used as type `StrKwargs6`. +callables_subtyping.py:196:4 Incompatible variable type [9]: f10 is declared to have type `Standard6` but is used as type `IntStrKwargs6`. +callables_subtyping.py:197:4 Incompatible variable type [9]: f11 is declared to have type `Standard6` but is used as type `StrKwargs6`. +callables_subtyping.py:208:0 Incompatible variable type [9]: TypeAliasWithP is declared to have type `TypeAlias` but is used as type `Type[typing.Callable[..., Variable[$synthetic_attribute_resolution_variable]]]`. +callables_subtyping.py:208:37 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[ParamSpec, None]`. +callables_subtyping.py:211:39 Undefined or invalid type [11]: Annotation `TypeAliasWithP` is not defined as a type. +callables_subtyping.py:237:4 Incompatible variable type [9]: f2 is declared to have type `DefaultArg8` but is used as type `NoX8`. +callables_subtyping.py:240:4 Incompatible variable type [9]: f4 is declared to have type `NoDefaultArg8` but is used as type `NoX8`. +callables_subtyping.py:243:4 Incompatible variable type [9]: f6 is declared to have type `NoX8` but is used as type `NoDefaultArg8`. +callables_subtyping.py:253:4 Missing overload implementation [42]: Overloaded function `Overloaded9.__call__` must have an implementation. +callables_subtyping.py:273:4 Incompatible variable type [9]: f3 is declared to have type `FloatArg9` but is used as type `Overloaded9`. +callables_subtyping.py:282:4 Missing overload implementation [42]: Overloaded function `Overloaded10.__call__` must have an implementation. +callables_subtyping.py:297:4 Incompatible variable type [9]: f2 is declared to have type `Overloaded10` but is used as type `StrArg10`. +""" +conformance_automated = "Fail" diff --git a/conformance/results/pyre/version.toml b/conformance/results/pyre/version.toml index 10179a617..6c4e3accd 100644 --- a/conformance/results/pyre/version.toml +++ b/conformance/results/pyre/version.toml @@ -1,2 +1,2 @@ version = "pyre 0.9.19" -test_duration = 3.7 +test_duration = 4.1 diff --git a/conformance/results/pyright/callables_annotation.toml b/conformance/results/pyright/callables_annotation.toml index b432d4228..c022cb9db 100644 --- a/conformance/results/pyright/callables_annotation.toml +++ b/conformance/results/pyright/callables_annotation.toml @@ -1,18 +1,53 @@ -conformant = "Pass" +conformant = "Partial" +notes = """ +Does not treat "*args: Any, **kwargs: Any" as "...". +""" output = """ -callables_annotation.py:13:5 - error: Expected 1 more positional argument (reportCallIssue) -callables_annotation.py:14:11 - error: Argument of type "Literal[2]" cannot be assigned to parameter of type "str" +callables_annotation.py:25:5 - error: Expected 1 more positional argument (reportCallIssue) +callables_annotation.py:26:11 - error: Argument of type "Literal[2]" cannot be assigned to parameter of type "str"   "Literal[2]" is incompatible with "str" (reportArgumentType) -callables_annotation.py:15:15 - error: Expected 2 positional arguments (reportCallIssue) -callables_annotation.py:17:10 - error: Expected 2 more positional arguments (reportCallIssue) -callables_annotation.py:23:8 - error: Expected 0 positional arguments (reportCallIssue) -callables_annotation.py:40:14 - error: Expected parameter type list or "..." -callables_annotation.py:41:14 - error: Expected parameter type list or "..." -callables_annotation.py:42:18 - error: List expression not allowed for this type argument -callables_annotation.py:43:14 - error: Expected parameter type list or "..." -callables_annotation.py:43:24 - error: Expected only two type arguments to "Callable" -callables_annotation.py:44:15 - error: "..." is not allowed in this context +callables_annotation.py:27:15 - error: Expected 2 positional arguments (reportCallIssue) +callables_annotation.py:29:10 - error: Expected 2 more positional arguments (reportCallIssue) +callables_annotation.py:35:8 - error: Expected 0 positional arguments (reportCallIssue) +callables_annotation.py:55:14 - error: Expected parameter type list or "..." +callables_annotation.py:56:14 - error: Expected parameter type list or "..." +callables_annotation.py:57:18 - error: List expression not allowed for this type argument +callables_annotation.py:58:14 - error: Expected parameter type list or "..." +callables_annotation.py:58:24 - error: Expected only two type arguments to "Callable" +callables_annotation.py:59:15 - error: "..." is not allowed in this context +callables_annotation.py:91:7 - error: Expression of type "() -> str" is incompatible with declared type "(int, ...) -> str" +  Type "() -> str" is incompatible with type "(int, ...) -> str" +    Function accepts too many positional parameters; expected 0 but received 2 (reportAssignmentType) +callables_annotation.py:93:7 - error: Expression of type "(*, a: int) -> str" is incompatible with declared type "(int, ...) -> str" +  Type "(*, a: int) -> str" is incompatible with type "(int, ...) -> str" +    Function accepts too many positional parameters; expected 0 but received 2 (reportAssignmentType) +callables_annotation.py:133:17 - error: "assert_type" mismatch: expected "(...) -> None" but received "Proto1" (reportAssertTypeFailure) +callables_annotation.py:134:17 - error: "assert_type" mismatch: expected "Proto5[Any]" but received "Proto1" (reportAssertTypeFailure) +callables_annotation.py:135:17 - error: "assert_type" mismatch: expected "(int, ...) -> None" but received "Proto2" (reportAssertTypeFailure) +callables_annotation.py:136:17 - error: "assert_type" mismatch: expected "(...) -> None" but received "Proto3" (reportAssertTypeFailure) +callables_annotation.py:137:17 - error: "assert_type" mismatch: expected "Proto4[...]" but received "Proto3" (reportAssertTypeFailure) +callables_annotation.py:139:18 - error: Expression of type "Proto7" is incompatible with declared type "Proto6" +  "Proto7" is incompatible with protocol "Proto6" +    "__call__" is an incompatible type +      Type "(a: float, /, b: int, *, k: str, m: str) -> None" is incompatible with type "(a: int, /, *args: Any, k: str, **kwargs: Any) -> None" +        Parameter "*args" has no corresponding parameter +        Parameter "**kwargs" has no corresponding parameter (reportAssignmentType) +callables_annotation.py:152:26 - error: Expression of type "() -> str" is incompatible with declared type "Callback2[...]" +  Type "() -> str" is incompatible with type "Callback2[...]" +    Function accepts too many positional parameters; expected 0 but received 2 (reportAssignmentType) +callables_annotation.py:167:48 - error: Expression of type "(int, str) -> str" is incompatible with declared type "(str, ...) -> str" +  Type "(int, str) -> str" is incompatible with type "(str, ...) -> str" +    Parameter 1: type "str" is incompatible with type "int" +      "str" is incompatible with "int" (reportAssignmentType) +callables_annotation.py:169:32 - error: Expression of type "(int, str) -> str" is incompatible with declared type "CallbackWithStr[...]" +  Type "(int, str) -> str" is incompatible with type "CallbackWithStr[...]" +    Parameter 1: type "str" is incompatible with type "int" +      "str" is incompatible with "int" (reportAssignmentType) """ -conformance_automated = "Pass" +conformance_automated = "Fail" errors_diff = """ +Line 133: Unexpected errors ['callables_annotation.py:133:17 - error: "assert_type" mismatch: expected "(...) -> None" but received "Proto1" (reportAssertTypeFailure)'] +Line 135: Unexpected errors ['callables_annotation.py:135:17 - error: "assert_type" mismatch: expected "(int, ...) -> None" but received "Proto2" (reportAssertTypeFailure)'] +Line 137: Unexpected errors ['callables_annotation.py:137:17 - error: "assert_type" mismatch: expected "Proto4[...]" but received "Proto3" (reportAssertTypeFailure)'] +Line 139: Unexpected errors ['callables_annotation.py:139:18 - error: Expression of type "Proto7" is incompatible with declared type "Proto6"'] """ diff --git a/conformance/results/pyright/callables_subtyping.toml b/conformance/results/pyright/callables_subtyping.toml new file mode 100644 index 000000000..3bd89cafe --- /dev/null +++ b/conformance/results/pyright/callables_subtyping.toml @@ -0,0 +1,193 @@ +conformant = "Pass" +errors_diff = """ +""" +output = """ +callables_subtyping.py:26:36 - error: Expression of type "(int) -> int" is incompatible with declared type "(float) -> float" +  Type "(int) -> int" is incompatible with type "(float) -> float" +    Parameter 1: type "float" is incompatible with type "int" +      "float" is incompatible with "int" (reportAssignmentType) +callables_subtyping.py:29:32 - error: Expression of type "(float) -> float" is incompatible with declared type "(int) -> int" +  Type "(float) -> float" is incompatible with type "(int) -> int" +    Function return type "float" is incompatible with type "int" +      "float" is incompatible with "int" (reportAssignmentType) +callables_subtyping.py:51:21 - error: Expression of type "PosOnly2" is incompatible with declared type "Standard2" +  "PosOnly2" is incompatible with protocol "Standard2" +    "__call__" is an incompatible type +      Type "(b: int, a: int, /) -> None" is incompatible with type "(a: int, b: int) -> None" +        Position-only parameter mismatch; parameter "a" is not position-only +        Position-only parameter mismatch; parameter "b" is not position-only +        Position-only parameter mismatch; expected 2 but received 0 (reportAssignmentType) +callables_subtyping.py:52:21 - error: Expression of type "KwOnly2" is incompatible with declared type "Standard2" +  "KwOnly2" is incompatible with protocol "Standard2" +    "__call__" is an incompatible type +      Type "(*, b: int, a: int) -> None" is incompatible with type "(a: int, b: int) -> None" +        Function accepts too many positional parameters; expected 0 but received 2 +          Keyword parameter "b" is missing in destination +          Keyword parameter "a" is missing in destination (reportAssignmentType) +callables_subtyping.py:55:20 - error: Expression of type "KwOnly2" is incompatible with declared type "PosOnly2" +  "KwOnly2" is incompatible with protocol "PosOnly2" +    "__call__" is an incompatible type +      Type "(*, b: int, a: int) -> None" is incompatible with type "(b: int, a: int, /) -> None" +        Function accepts too many positional parameters; expected 0 but received 2 +          Keyword parameter "b" is missing in destination +          Keyword parameter "a" is missing in destination (reportAssignmentType) +callables_subtyping.py:58:19 - error: Expression of type "PosOnly2" is incompatible with declared type "KwOnly2" +  "PosOnly2" is incompatible with protocol "KwOnly2" +    "__call__" is an incompatible type +      Type "(b: int, a: int, /) -> None" is incompatible with type "(*, b: int, a: int) -> None" +        Position-only parameter mismatch; expected 2 but received 0 +        Keyword parameter "b" is missing in source +        Keyword parameter "a" is missing in source (reportAssignmentType) +callables_subtyping.py:82:20 - error: Expression of type "NoArgs3" is incompatible with declared type "IntArgs3" +  "NoArgs3" is incompatible with protocol "IntArgs3" +    "__call__" is an incompatible type +      Type "() -> None" is incompatible with type "(*args: int) -> None" +        Parameter "*args" has no corresponding parameter (reportAssignmentType) +callables_subtyping.py:85:22 - error: Expression of type "NoArgs3" is incompatible with declared type "FloatArgs3" +  "NoArgs3" is incompatible with protocol "FloatArgs3" +    "__call__" is an incompatible type +      Type "() -> None" is incompatible with type "(*args: float) -> None" +        Parameter "*args" has no corresponding parameter (reportAssignmentType) +callables_subtyping.py:86:22 - error: Expression of type "IntArgs3" is incompatible with declared type "FloatArgs3" +  "IntArgs3" is incompatible with protocol "FloatArgs3" +    "__call__" is an incompatible type +      Type "(*args: int) -> None" is incompatible with type "(*args: float) -> None" +        Parameter 1: type "*tuple[float, ...]" is incompatible with type "*tuple[int, ...]" +          "*tuple[float, ...]" is incompatible with "*tuple[int, ...]" (reportAssignmentType) +callables_subtyping.py:116:20 - error: Expression of type "IntArgs4" is incompatible with declared type "PosOnly4" +  "IntArgs4" is incompatible with protocol "PosOnly4" +    "__call__" is an incompatible type +      Type "(*args: int) -> None" is incompatible with type "(a: int, b: str, /) -> None" +        Parameter 2: type "str" is incompatible with type "int" +          "str" is incompatible with "int" (reportAssignmentType) +callables_subtyping.py:119:23 - error: Expression of type "StrArgs4" is incompatible with declared type "IntStrArgs4" +  "StrArgs4" is incompatible with protocol "IntStrArgs4" +    "__call__" is an incompatible type +      Type "(a: int, /, *args: str) -> None" is incompatible with type "(*args: int | str) -> None" +        Parameter 2: type "int | str" is incompatible with type "str" +          Type "int | str" is incompatible with type "str" +        Parameter 1: type "*tuple[int | str, ...]" is incompatible with type "*tuple[str, ...]" +          "*tuple[int | str, ...]" is incompatible with "*tuple[str, ...]" (reportAssignmentType) +callables_subtyping.py:120:23 - error: Expression of type "IntArgs4" is incompatible with declared type "IntStrArgs4" +  "IntArgs4" is incompatible with protocol "IntStrArgs4" +    "__call__" is an incompatible type +      Type "(*args: int) -> None" is incompatible with type "(*args: int | str) -> None" +        Parameter 1: type "*tuple[int | str, ...]" is incompatible with type "*tuple[int, ...]" +          "*tuple[int | str, ...]" is incompatible with "*tuple[int, ...]" (reportAssignmentType) +callables_subtyping.py:122:20 - error: Expression of type "IntArgs4" is incompatible with declared type "StrArgs4" +  "IntArgs4" is incompatible with protocol "StrArgs4" +    "__call__" is an incompatible type +      Type "(*args: int) -> None" is incompatible with type "(a: int, /, *args: str) -> None" +        Parameter 2: type "str" is incompatible with type "int" +          "str" is incompatible with "int" +        Parameter 3: type "*tuple[str, ...]" is incompatible with type "*tuple[int, ...]" +          "*tuple[str, ...]" is incompatible with "*tuple[int, ...]" (reportAssignmentType) +callables_subtyping.py:124:20 - error: Expression of type "StrArgs4" is incompatible with declared type "IntArgs4" +  "StrArgs4" is incompatible with protocol "IntArgs4" +    "__call__" is an incompatible type +      Type "(a: int, /, *args: str) -> None" is incompatible with type "(*args: int) -> None" +        Parameter 2: type "int" is incompatible with type "str" +          "int" is incompatible with "str" +        Parameter 1: type "*tuple[int, ...]" is incompatible with type "*tuple[str, ...]" +          "*tuple[int, ...]" is incompatible with "*tuple[str, ...]" (reportAssignmentType) +callables_subtyping.py:125:22 - error: Expression of type "IntStrArgs4" is incompatible with declared type "Standard4" +  "IntStrArgs4" is incompatible with protocol "Standard4" +    "__call__" is an incompatible type +      Type "(*args: int | str) -> None" is incompatible with type "(a: int, b: str) -> None" +        Keyword parameter "b" is missing in source (reportAssignmentType) +callables_subtyping.py:126:22 - error: Expression of type "StrArgs4" is incompatible with declared type "Standard4" +  "StrArgs4" is incompatible with protocol "Standard4" +    "__call__" is an incompatible type +      Type "(a: int, /, *args: str) -> None" is incompatible with type "(a: int, b: str) -> None" +        Position-only parameter mismatch; parameter "a" is not position-only +        Position-only parameter mismatch; expected 1 but received 0 (reportAssignmentType) +callables_subtyping.py:151:22 - error: Expression of type "NoKwargs5" is incompatible with declared type "IntKwargs5" +  "NoKwargs5" is incompatible with protocol "IntKwargs5" +    "__call__" is an incompatible type +      Type "() -> None" is incompatible with type "(**kwargs: int) -> None" +        Parameter "**kwargs" has no corresponding parameter (reportAssignmentType) +callables_subtyping.py:154:24 - error: Expression of type "NoKwargs5" is incompatible with declared type "FloatKwargs5" +  "NoKwargs5" is incompatible with protocol "FloatKwargs5" +    "__call__" is an incompatible type +      Type "() -> None" is incompatible with type "(**kwargs: float) -> None" +        Parameter "**kwargs" has no corresponding parameter (reportAssignmentType) +callables_subtyping.py:155:24 - error: Expression of type "IntKwargs5" is incompatible with declared type "FloatKwargs5" +  "IntKwargs5" is incompatible with protocol "FloatKwargs5" +    "__call__" is an incompatible type +      Type "(**kwargs: int) -> None" is incompatible with type "(**kwargs: float) -> None" +        Parameter 1: type "float" is incompatible with type "int" +          "float" is incompatible with "int" (reportAssignmentType) +callables_subtyping.py:187:19 - error: Expression of type "IntKwargs6" is incompatible with declared type "KwOnly6" +  "IntKwargs6" is incompatible with protocol "KwOnly6" +    "__call__" is an incompatible type +      Type "(**kwargs: int) -> None" is incompatible with type "(*, a: int, b: str) -> None" +        Parameter 3: type "str" is incompatible with type "int" +          "str" is incompatible with "int" (reportAssignmentType) +callables_subtyping.py:190:25 - error: Expression of type "StrKwargs6" is incompatible with declared type "IntStrKwargs6" +  "StrKwargs6" is incompatible with protocol "IntStrKwargs6" +    "__call__" is an incompatible type +      Type "(*, a: int, **kwargs: str) -> None" is incompatible with type "(**kwargs: int | str) -> None" +        Parameter 1: type "int | str" is incompatible with type "int" +          Type "int | str" is incompatible with type "int" +        Parameter 1: type "int | str" is incompatible with type "str" +          Type "int | str" is incompatible with type "str" (reportAssignmentType) +callables_subtyping.py:191:25 - error: Expression of type "IntKwargs6" is incompatible with declared type "IntStrKwargs6" +  "IntKwargs6" is incompatible with protocol "IntStrKwargs6" +    "__call__" is an incompatible type +      Type "(**kwargs: int) -> None" is incompatible with type "(**kwargs: int | str) -> None" +        Parameter 1: type "int | str" is incompatible with type "int" +          Type "int | str" is incompatible with type "int" (reportAssignmentType) +callables_subtyping.py:193:22 - error: Expression of type "IntKwargs6" is incompatible with declared type "StrKwargs6" +  "IntKwargs6" is incompatible with protocol "StrKwargs6" +    "__call__" is an incompatible type +      Type "(**kwargs: int) -> None" is incompatible with type "(*, a: int, **kwargs: str) -> None" +        Parameter 3: type "str" is incompatible with type "int" +          "str" is incompatible with "int" (reportAssignmentType) +callables_subtyping.py:195:22 - error: Expression of type "StrKwargs6" is incompatible with declared type "IntKwargs6" +  "StrKwargs6" is incompatible with protocol "IntKwargs6" +    "__call__" is an incompatible type +      Type "(*, a: int, **kwargs: str) -> None" is incompatible with type "(**kwargs: int) -> None" +        Parameter 1: type "int" is incompatible with type "str" +          "int" is incompatible with "str" (reportAssignmentType) +callables_subtyping.py:196:22 - error: Expression of type "IntStrKwargs6" is incompatible with declared type "Standard6" +  "IntStrKwargs6" is incompatible with protocol "Standard6" +    "__call__" is an incompatible type +      Type "(**kwargs: int | str) -> None" is incompatible with type "(a: int, b: str) -> None" +        Function accepts too many positional parameters; expected 0 but received 2 (reportAssignmentType) +callables_subtyping.py:197:22 - error: Expression of type "StrKwargs6" is incompatible with declared type "Standard6" +  "StrKwargs6" is incompatible with protocol "Standard6" +    "__call__" is an incompatible type +      Type "(*, a: int, **kwargs: str) -> None" is incompatible with type "(a: int, b: str) -> None" +        Function accepts too many positional parameters; expected 0 but received 2 +          Keyword parameter "a" is missing in destination (reportAssignmentType) +callables_subtyping.py:236:23 - error: Expression of type "NoDefaultArg8" is incompatible with declared type "DefaultArg8" +  "NoDefaultArg8" is incompatible with protocol "DefaultArg8" +    "__call__" is an incompatible type +      Type "(x: int) -> None" is incompatible with type "(x: int = 0) -> None" +        Parameter "x" is missing default argument (reportAssignmentType) +callables_subtyping.py:237:23 - error: Expression of type "NoX8" is incompatible with declared type "DefaultArg8" +  "NoX8" is incompatible with protocol "DefaultArg8" +    "__call__" is an incompatible type +      Type "() -> None" is incompatible with type "(x: int = 0) -> None" +        Function accepts too many positional parameters; expected 0 but received 1 (reportAssignmentType) +callables_subtyping.py:240:25 - error: Expression of type "NoX8" is incompatible with declared type "NoDefaultArg8" +  "NoX8" is incompatible with protocol "NoDefaultArg8" +    "__call__" is an incompatible type +      Type "() -> None" is incompatible with type "(x: int) -> None" +        Function accepts too many positional parameters; expected 0 but received 1 (reportAssignmentType) +callables_subtyping.py:243:16 - error: Expression of type "NoDefaultArg8" is incompatible with declared type "NoX8" +  "NoDefaultArg8" is incompatible with protocol "NoX8" +    "__call__" is an incompatible type +      Type "(x: int) -> None" is incompatible with type "() -> None" (reportAssignmentType) +callables_subtyping.py:273:21 - error: Expression of type "Overloaded9" is incompatible with declared type "FloatArg9" +  "Overloaded9" is incompatible with protocol "FloatArg9" +    "__call__" is an incompatible type +      No overloaded function matches type "(x: float) -> float" (reportAssignmentType) +callables_subtyping.py:297:24 - error: Expression of type "StrArg10" is incompatible with declared type "Overloaded10" +  "StrArg10" is incompatible with protocol "Overloaded10" +    "__call__" is an incompatible type +      One or more overloads of "__call__" is not assignable +        Type "(x: str) -> complex" is incompatible with type "(x: int, y: str) -> float" +          Function accepts too many positional parameters; expected 1 but received 2 (reportAssignmentType) +""" +conformance_automated = "Pass" diff --git a/conformance/results/pytype/callables_annotation.toml b/conformance/results/pytype/callables_annotation.toml index 518d2530d..33126141e 100644 --- a/conformance/results/pytype/callables_annotation.toml +++ b/conformance/results/pytype/callables_annotation.toml @@ -1,18 +1,28 @@ -conformant = "Pass" +conformant = "Partial" +notes = """ +Does not support Concatenate. +Does not treat "*args: Any, **kwargs: Any" as "...". +""" output = """ -File "callables_annotation.py", line 13, in func1: Function expects 2 arg(s), got 1 [wrong-arg-count] -File "callables_annotation.py", line 14, in func1: Function was called with the wrong arguments [wrong-arg-types] -File "callables_annotation.py", line 15, in func1: Function expects 2 arg(s), got 3 [wrong-arg-count] -File "callables_annotation.py", line 17, in func1: Invalid keyword arguments (a, b) to function [wrong-keyword-args] -File "callables_annotation.py", line 23, in func2: Function expects 0 arg(s), got 1 [wrong-arg-count] -File "callables_annotation.py", line 40, in : Invalid type annotation 'int' [invalid-annotation] -File "callables_annotation.py", line 40, in : Invalid type annotation 'Callable[Any]' [invalid-annotation] -File "callables_annotation.py", line 41, in : Invalid type annotation 'int' [invalid-annotation] -File "callables_annotation.py", line 42, in : Invalid type annotation '[int]' [invalid-annotation] -File "callables_annotation.py", line 43, in : Invalid type annotation 'int' [invalid-annotation] -File "callables_annotation.py", line 43, in : Invalid type annotation 'Callable[Any, int, int]' [invalid-annotation] -File "callables_annotation.py", line 44, in : Invalid type annotation 'Ellipsis' [invalid-annotation] +AttributeError: 'Concatenate' object has no attribute 'formal_type_parameters' """ -conformance_automated = "Pass" +conformance_automated = "Fail" errors_diff = """ +Line 25: Expected 1 errors +Line 26: Expected 1 errors +Line 27: Expected 1 errors +Line 29: Expected 1 errors +Line 35: Expected 1 errors +Line 55: Expected 1 errors +Line 56: Expected 1 errors +Line 57: Expected 1 errors +Line 58: Expected 1 errors +Line 59: Expected 1 errors +Line 91: Expected 1 errors +Line 93: Expected 1 errors +Line 134: Expected 1 errors +Line 136: Expected 1 errors +Line 152: Expected 1 errors +Line 167: Expected 1 errors +Line 169: Expected 1 errors """ diff --git a/conformance/results/pytype/callables_subtyping.toml b/conformance/results/pytype/callables_subtyping.toml new file mode 100644 index 000000000..43e7ac96b --- /dev/null +++ b/conformance/results/pytype/callables_subtyping.toml @@ -0,0 +1,50 @@ +conformant = "Partial" +notes = """ +Does not detect many subtyping rule violations for callables. +Does not correctly handle type alias parameterized by ParamSpec. +""" +errors_diff = """ +Line 51: Expected 1 errors +Line 52: Expected 1 errors +Line 55: Expected 1 errors +Line 58: Expected 1 errors +Line 82: Expected 1 errors +Line 85: Expected 1 errors +Line 86: Expected 1 errors +Line 116: Expected 1 errors +Line 119: Expected 1 errors +Line 120: Expected 1 errors +Line 122: Expected 1 errors +Line 124: Expected 1 errors +Line 125: Expected 1 errors +Line 126: Expected 1 errors +Line 151: Expected 1 errors +Line 154: Expected 1 errors +Line 155: Expected 1 errors +Line 187: Expected 1 errors +Line 190: Expected 1 errors +Line 191: Expected 1 errors +Line 193: Expected 1 errors +Line 195: Expected 1 errors +Line 196: Expected 1 errors +Line 197: Expected 1 errors +Line 236: Expected 1 errors +Line 237: Expected 1 errors +Line 240: Expected 1 errors +Line 243: Expected 1 errors +Line 273: Expected 1 errors +Line 297: Expected 1 errors +Line 211: Unexpected errors ['File "callables_subtyping.py", line 211, in : Invalid type annotation \\'Callable[[P], None][P]\\' [invalid-annotation]'] +Line 213: Unexpected errors ['File "callables_subtyping.py", line 213, in func7: Invalid type annotation \\'TypeAliasWithP[P]\\' [invalid-annotation]'] +Line 255: Unexpected errors ['File "callables_subtyping.py", line 255, in __call__: @typing.overload-decorated \\'Overloaded9.__call__\\' object is not callable [not-callable]'] +Line 284: Unexpected errors ['File "callables_subtyping.py", line 284, in __call__: @typing.overload-decorated \\'Overloaded10.__call__\\' object is not callable [not-callable]'] +""" +output = """ +File "callables_subtyping.py", line 26, in func1: Type annotation for f6 does not match type of assignment [annotation-type-mismatch] +File "callables_subtyping.py", line 29, in func1: Type annotation for f8 does not match type of assignment [annotation-type-mismatch] +File "callables_subtyping.py", line 211, in : Invalid type annotation 'Callable[[P], None][P]' [invalid-annotation] +File "callables_subtyping.py", line 213, in func7: Invalid type annotation 'TypeAliasWithP[P]' [invalid-annotation] +File "callables_subtyping.py", line 255, in __call__: @typing.overload-decorated 'Overloaded9.__call__' object is not callable [not-callable] +File "callables_subtyping.py", line 284, in __call__: @typing.overload-decorated 'Overloaded10.__call__' object is not callable [not-callable] +""" +conformance_automated = "Fail" diff --git a/conformance/results/pytype/version.toml b/conformance/results/pytype/version.toml index 9dad1ba27..f5cce04d0 100644 --- a/conformance/results/pytype/version.toml +++ b/conformance/results/pytype/version.toml @@ -1,2 +1,2 @@ version = "pytype 2024.04.11" -test_duration = 35.5 +test_duration = 38.5 diff --git a/conformance/results/results.html b/conformance/results/results.html index 26289a451..4c525fd78 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -165,10 +165,10 @@

Python Type System Conformance Test Results

1.6sec
pyre 0.9.19
-
3.7sec
+
4.1sec
pytype 2024.04.11
-
35.5sec
+
38.5sec
@@ -601,10 +601,10 @@

Python Type System Conformance Test Results

Callables      callables_annotation -Pass -Pass -
Partial

Does not evaluate correct type for `*args: int` parameter.

Does not reject illegal form `Callable[[...], int]`.

-Pass +
Partial

Incorrectly treats "*args: T, **kwargs: T" as "..." when T is specialized to Any.

Does not treat "*args: Any, **kargs: Any" as "..." when separated by keyword parameter.

+
Partial

Does not treat "*args: Any, **kwargs: Any" as "...".

+
Partial

Does not evaluate correct type for `*args: int` parameter.

Does not reject illegal form `Callable[[...], int]`.

Does not correctly implement type compatibility rules for "...".

Does not treat "*args: Any, **kwargs: Any" as "...".

+
Partial

Does not support Concatenate.

Does not treat "*args: Any, **kwargs: Any" as "...".

     callables_kwargs Pass @@ -618,6 +618,12 @@

Python Type System Conformance Test Results

Partial

Does not correctly handle callback protocol that declares attributes in all functions.

Does not report type incompatibility for callback protocol with positional-only parameters.

Incorrectly reports type compatibility error with callback that has *args and **kwargs.

Does not report type incompatibility for callback missing a default argument for positional parameter.

Does not report type incompatibility for callback missing a default argument for keyword parameter.

Unsupported

Does not properly handle type compatibility checks with callback protocols.

+     callables_subtyping +Pass +Pass +
Partial

Rejects standard parameter as incompatible with keyword-only parameter.

Rejects use of Callable with ParamSpec in TypeAlias definition.

+
Partial

Does not detect many subtyping rule violations for callables.

Does not correctly handle type alias parameterized by ParamSpec.

+ Constructors diff --git a/conformance/tests/callables_annotation.py b/conformance/tests/callables_annotation.py index d139be56a..af6a41671 100644 --- a/conformance/tests/callables_annotation.py +++ b/conformance/tests/callables_annotation.py @@ -4,7 +4,19 @@ # Specification: https://typing.readthedocs.io/en/latest/spec/callables.html#callable -from typing import Callable, assert_type +from typing import ( + Any, + Callable, + Concatenate, + ParamSpec, + Protocol, + TypeAlias, + TypeVar, + assert_type, +) + +T_contra = TypeVar("T_contra", contravariant=True) +P = ParamSpec("P") def func1(cb: Callable[[int, str], list[str]]) -> None: @@ -23,9 +35,12 @@ def func2(cb: Callable[[], dict[str, str]]) -> None: cb(1) # E -# > It is possible to declare the return type of a callable without specifying -# > the call signature by substituting a literal ellipsis (three dots) for the -# > list of arguments. +# https://typing.readthedocs.io/en/latest/spec/callables.html#meaning-of-in-callable + + +# > The Callable special form supports the use of ... in place of the list of +# > parameter types. This indicates that the type is consistent with any input +# > signature. def func3(cb: Callable[..., list[str]]): assert_type(cb(), list[str]) assert_type(cb(""), list[str]) @@ -42,3 +57,113 @@ def func4(*args: int, **kwargs: int) -> None: v3: Callable[[], [int]] # E v4: Callable[int, int, int] # E v5: Callable[[...], int] # E + + +def test_cb1(x: int) -> str: + return "" + + +def test_cb2() -> str: + return "" + + +cb1: Callable[..., str] +cb1 = test_cb1 # OK +cb1 = test_cb2 # OK + +cb2: Callable[[], str] = cb1 # OK + +# > A ... can also be used with Concatenate. In this case, the parameters prior +# > to the ... are required to be present in the input signature and be +# > compatible in kind and type, but any additional parameters are permitted. + + +def test_cb3(a: int, b: int, c: int) -> str: + return "" + + +def test_cb4(*, a: int) -> str: + return "" + + +cb3: Callable[Concatenate[int, ...], str] +cb3 = test_cb1 # OK +cb3 = test_cb2 # E +cb3 = test_cb3 # OK +cb3 = test_cb4 # E + +# > If the input signature in a function definition includes both a *args and +# > **kwargs parameter and both are typed as Any (explicitly or implicitly +# > because it has no annotation), a type checker should treat this as the +# > equivalent of `...`. Any other parameters in the signature are unaffected +# > and are retained as part of the signature. + + +class Proto1(Protocol): + def __call__(self, *args: Any, **kwargs: Any) -> None: ... + + +class Proto2(Protocol): + def __call__(self, a: int, /, *args, **kwargs) -> None: ... + + +class Proto3(Protocol): + def __call__(self, a: int, *args: Any, **kwargs: Any) -> None: ... + + +class Proto4(Protocol[P]): + def __call__(self, a: int, *args: P.args, **kwargs: P.kwargs) -> None: ... + + +class Proto5(Protocol[T_contra]): + def __call__(self, *args: T_contra, **kwargs: T_contra) -> None: ... + + +class Proto6(Protocol): + def __call__(self, a: int, /, *args: Any, k: str, **kwargs: Any) -> None: + pass + + +class Proto7(Protocol): + def __call__(self, a: float, /, b: int, *, k: str, m: str) -> None: + pass + + +def func(p1: Proto1, p2: Proto2, p3: Proto3, p7: Proto7): + assert_type(p1, Callable[..., None]) # OK + assert_type(p1, Proto5[Any]) # E + assert_type(p2, Callable[Concatenate[int, ...], None]) # OK + assert_type(p3, Callable[..., None]) # E + assert_type(p3, Proto4[...]) # OK + + f1: Proto6 = p7 # OK + + +# > The ... syntax can also be used to provide a specialized value for a +# > ParamSpec in a generic class or type alias. + + +Callback1: TypeAlias = Callable[P, str] +Callback2: TypeAlias = Callable[Concatenate[int, P], str] + + +def func5(cb1: Callable[[], str], cb2: Callable[[int], str]) -> None: + f1: Callback1[...] = cb1 # OK + f2: Callback2[...] = cb1 # E + + f3: Callback1[...] = cb2 # OK + f4: Callback2[...] = cb2 # OK + + +# > If ... is used with signature concatenation, the ... portion continues +# > to mean “any conceivable set of parameters that could be compatible”. + +CallbackWithInt: TypeAlias = Callable[Concatenate[int, P], str] +CallbackWithStr: TypeAlias = Callable[Concatenate[str, P], str] + + +def func6(cb: Callable[[int, str], str]) -> None: + f1: Callable[Concatenate[int, ...], str] = cb # OK + f2: Callable[Concatenate[str, ...], str] = cb # E + f3: CallbackWithInt[...] = cb # OK + f4: CallbackWithStr[...] = cb # E diff --git a/conformance/tests/callables_subtyping.py b/conformance/tests/callables_subtyping.py new file mode 100644 index 000000000..0451d6289 --- /dev/null +++ b/conformance/tests/callables_subtyping.py @@ -0,0 +1,297 @@ +""" +Tests subtyping rules for callables. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/callables.html#subtyping-rules-for-callables + +from typing import Callable, ParamSpec, Protocol, TypeAlias, overload + +P = ParamSpec("P") + +# > Callable types are covariant with respect to their return types but +# > contravariant with respect to their parameter types. + + +def func1( + cb1: Callable[[float], int], + cb2: Callable[[float], float], + cb3: Callable[[int], int], +) -> None: + f1: Callable[[int], float] = cb1 # OK + f2: Callable[[int], float] = cb2 # OK + f3: Callable[[int], float] = cb3 # OK + + f4: Callable[[float], float] = cb1 # OK + f5: Callable[[float], float] = cb2 # OK + f6: Callable[[float], float] = cb3 # E + + f7: Callable[[int], int] = cb1 # OK + f8: Callable[[int], int] = cb2 # E + f9: Callable[[int], int] = cb3 # OK + + +# > Callable A is a subtype of callable B if all keyword-only parameters in B +# > are present in A as either keyword-only parameters or standard (positional +# > or keyword) parameters. + + +class PosOnly2(Protocol): + def __call__(self, b: int, a: int, /) -> None: ... + + +class KwOnly2(Protocol): + def __call__(self, *, b: int, a: int) -> None: ... + + +class Standard2(Protocol): + def __call__(self, a: int, b: int) -> None: ... + + +def func2(standard: Standard2, pos_only: PosOnly2, kw_only: KwOnly2): + f1: Standard2 = pos_only # E + f2: Standard2 = kw_only # E + + f3: PosOnly2 = standard # OK + f4: PosOnly2 = kw_only # E + + f5: KwOnly2 = standard # OK + f6: KwOnly2 = pos_only # E + + +# > If a callable B has a signature with a *args parameter, callable A +# > must also have a *args parameter to be a subtype of B, and the type of +# > B’s *args parameter must be a subtype of A’s *args parameter. + + +class NoArgs3(Protocol): + def __call__(self) -> None: ... + + +class IntArgs3(Protocol): + def __call__(self, *args: int) -> None: ... + + +class FloatArgs3(Protocol): + def __call__(self, *args: float) -> None: ... + + +def func3(no_args: NoArgs3, int_args: IntArgs3, float_args: FloatArgs3): + f1: NoArgs3 = int_args # OK + f2: NoArgs3 = float_args # OK + + f3: IntArgs3 = no_args # E: missing *args parameter + f4: IntArgs3 = float_args # OK + + f5: FloatArgs3 = no_args # E: missing *args parameter + f6: FloatArgs3 = int_args # E: float is not subtype of int + + +# > If a callable B has a signature with one or more positional-only parameters, +# > a callable A is a subtype of B if A has an *args parameter whose type is a +# > supertype of the types of any otherwise-unmatched positional-only parameters +# > in B. + + +class PosOnly4(Protocol): + def __call__(self, a: int, b: str, /) -> None: ... + + +class IntArgs4(Protocol): + def __call__(self, *args: int) -> None: ... + + +class IntStrArgs4(Protocol): + def __call__(self, *args: int | str) -> None: ... + + +class StrArgs4(Protocol): + def __call__(self, a: int, /, *args: str) -> None: ... + + +class Standard4(Protocol): + def __call__(self, a: int, b: str) -> None: ... + + +def func4(int_args: IntArgs4, int_str_args: IntStrArgs4, str_args: StrArgs4): + f1: PosOnly4 = int_args # E: str is not subtype of int + f2: PosOnly4 = int_str_args # OK + f3: PosOnly4 = str_args # OK + f4: IntStrArgs4 = str_args # E: int | str is not subtype of str + f5: IntStrArgs4 = int_args # E: int | str is not subtype of int + f6: StrArgs4 = int_str_args # OK + f7: StrArgs4 = int_args # E: str is not subtype of int + f8: IntArgs4 = int_str_args # OK + f9: IntArgs4 = str_args # E: int is not subtype of str + f10: Standard4 = int_str_args # E: keyword parameters a and b missing + f11: Standard4 = str_args # E: keyword parameter b missing + + +# > If a callable B has a signature with a **kwargs parameter (without an +# > unpacked TypedDict type annotation), callable A must also have a **kwargs +# > parameter to be a subtype of B, and the type of B’s **kwargs parameter +# > must be a subtype of A’s **kwargs parameter. + + +class NoKwargs5(Protocol): + def __call__(self) -> None: ... + + +class IntKwargs5(Protocol): + def __call__(self, **kwargs: int) -> None: ... + + +class FloatKwargs5(Protocol): + def __call__(self, **kwargs: float) -> None: ... + + +def func5(no_kwargs: NoKwargs5, int_kwargs: IntKwargs5, float_kwargs: FloatKwargs5): + f1: NoKwargs5 = int_kwargs # OK + f2: NoKwargs5 = float_kwargs # OK + + f3: IntKwargs5 = no_kwargs # E: missing **kwargs parameter + f4: IntKwargs5 = float_kwargs # OK + + f5: FloatKwargs5 = no_kwargs # E: missing **kwargs parameter + f6: FloatKwargs5 = int_kwargs # E: float is not subtype of int + + +# > If a callable B has a signature with one or more keyword-only parameters, +# > a callable A is a subtype of B if A has a **kwargs parameter whose type +# > is a supertype of the types of any otherwise-unmatched keyword-only +# > parameters in B. + + +class KwOnly6(Protocol): + def __call__(self, *, a: int, b: str) -> None: ... + + +class IntKwargs6(Protocol): + def __call__(self, **kwargs: int) -> None: ... + + +class IntStrKwargs6(Protocol): + def __call__(self, **kwargs: int | str) -> None: ... + + +class StrKwargs6(Protocol): + def __call__(self, *, a: int, **kwargs: str) -> None: ... + + +class Standard6(Protocol): + def __call__(self, a: int, b: str) -> None: ... + + +def func6( + int_kwargs: IntKwargs6, int_str_kwargs: IntStrKwargs6, str_kwargs: StrKwargs6 +): + f1: KwOnly6 = int_kwargs # E: str is not subtype of int + f2: KwOnly6 = int_str_kwargs # OK + f3: KwOnly6 = str_kwargs # OK + f4: IntStrKwargs6 = str_kwargs # E: int | str is not subtype of str + f5: IntStrKwargs6 = int_kwargs # E: int | str is not subtype of int + f6: StrKwargs6 = int_str_kwargs # OK + f7: StrKwargs6 = int_kwargs # E: str is not subtype of int + f8: IntKwargs6 = int_str_kwargs # OK + f9: IntKwargs6 = str_kwargs # E: int is not subtype of str + f10: Standard6 = int_str_kwargs # E: Does not accept positional arguments + f11: Standard6 = str_kwargs # E: Does not accept positional arguments + + +# > A signature that includes *args: P.args, **kwargs: P.kwargs is equivalent +# > to a Callable parameterized by P. + + +class ProtocolWithP(Protocol[P]): + def __call__(self, *args: P.args, **kwargs: P.kwargs) -> None: ... + + +TypeAliasWithP: TypeAlias = Callable[P, None] + + +def func7(proto: ProtocolWithP[P], ta: TypeAliasWithP[P]): + # These two types are equivalent + f1: TypeAliasWithP[P] = proto # OK + f2: ProtocolWithP[P] = ta # OK + + +# > If a callable A has a parameter x with a default argument value and B is +# > the same as A except that x has no default argument, then A is a subtype +# > of B. A is also a subtype of C if C is the same as A with parameter x +# > removed. + + +class DefaultArg8(Protocol): + def __call__(self, x: int = 0) -> None: ... + + +class NoDefaultArg8(Protocol): + def __call__(self, x: int) -> None: ... + + +class NoX8(Protocol): + def __call__(self) -> None: ... + + +def func8(default_arg: DefaultArg8, no_default_arg: NoDefaultArg8, no_x: NoX8): + f1: DefaultArg8 = no_default_arg # E + f2: DefaultArg8 = no_x # E + + f3: NoDefaultArg8 = default_arg # OK + f4: NoDefaultArg8 = no_x # E + + f5: NoX8 = default_arg # OK + f6: NoX8 = no_default_arg # E + + +# > If a callable A is overloaded with two or more signatures, it is a subtype +# > of callable B if at least one of the overloaded signatures in A is a +# > subtype of B. + + +class Overloaded9(Protocol): + @overload + def __call__(self, x: int) -> int: ... + @overload + def __call__(self, x: str) -> str: ... + + +class IntArg9(Protocol): + def __call__(self, x: int) -> int: ... + + +class StrArg9(Protocol): + def __call__(self, x: str) -> str: ... + + +class FloatArg9(Protocol): + def __call__(self, x: float) -> float: ... + + +def func9(overloaded: Overloaded9): + f1: IntArg9 = overloaded # OK + f2: StrArg9 = overloaded # OK + f3: FloatArg9 = overloaded # E + + +# > If a callable B is overloaded with two or more signatures, callable A is +# > a subtype of B if A is a subtype of all of the signatures in B. + + +class Overloaded10(Protocol): + @overload + def __call__(self, x: int, y: str) -> float: ... + @overload + def __call__(self, x: str) -> complex: ... + + +class StrArg10(Protocol): + def __call__(self, x: str) -> complex: ... + + +class IntStrArg10(Protocol): + def __call__(self, x: int | str, y: str = "") -> int: ... + + +def func10(int_str_arg: IntStrArg10, str_arg: StrArg10): + f1: Overloaded10 = int_str_arg # OK + f2: Overloaded10 = str_arg # E