From d9d82c9b3900383f431304d8d7d69ba9f8e2486a Mon Sep 17 00:00:00 2001 From: kotlinisland <65446343+kotlinisland@users.noreply.github.com> Date: Mon, 9 Mar 2026 12:58:09 +1000 Subject: [PATCH] don't state that a parameter specification is always invariant --- .../mypy/generics_paramspec_semantics.toml | 20 +++++++++-- .../pyrefly/generics_paramspec_semantics.toml | 20 +++++++++-- .../pyright/generics_paramspec_semantics.toml | 30 +++++++++++++++-- conformance/results/results.html | 8 ++--- .../zuban/generics_paramspec_semantics.toml | 18 +++++++++- .../tests/generics_paramspec_semantics.py | 33 +++++++++++++++++++ docs/spec/generics.rst | 5 ++- 7 files changed, 120 insertions(+), 14 deletions(-) diff --git a/conformance/results/mypy/generics_paramspec_semantics.toml b/conformance/results/mypy/generics_paramspec_semantics.toml index 7dc429c76..9a607499c 100644 --- a/conformance/results/mypy/generics_paramspec_semantics.toml +++ b/conformance/results/mypy/generics_paramspec_semantics.toml @@ -1,4 +1,4 @@ -conformant = "Pass" +conformant = "Partial" output = """ generics_paramspec_semantics.py:26: error: Unexpected keyword argument "a" [call-arg] generics_paramspec_semantics.py:26: error: Unexpected keyword argument "b" [call-arg] @@ -11,7 +11,23 @@ generics_paramspec_semantics.py:127: error: Argument 1 to "expects_int_first" ha generics_paramspec_semantics.py:127: note: This is likely because "one" has named arguments: "x". Consider marking them positional-only generics_paramspec_semantics.py:132: error: Argument 1 to "expects_int_first" has incompatible type "def two(*, x: int) -> int"; expected "def (int, /, *, x: int) -> int" [arg-type] generics_paramspec_semantics.py:137: error: Argument 1 to "expects_int_first" has incompatible type "def three(**kwargs: int) -> int"; expected "def (int, /, **kwargs: int) -> int" [arg-type] +generics_paramspec_semantics.py:151: error: Incompatible types in assignment (expression has type "ContravariantParamSpec[[int]]", variable has type "ContravariantParamSpec[[object]]") [assignment] +generics_paramspec_semantics.py:155: error: Missing return statement [empty-body] +generics_paramspec_semantics.py:158: error: Incompatible types in assignment (expression has type "CovariantParamSpec[[int]]", variable has type "CovariantParamSpec[[object]]") [assignment] +generics_paramspec_semantics.py:161: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc] +generics_paramspec_semantics.py:164: error: Missing return statement [empty-body] +generics_paramspec_semantics.py:168: error: Incompatible types in assignment (expression has type "ContravariantParamSpecOld[[int]]", variable has type "ContravariantParamSpecOld[[object]]") [assignment] +generics_paramspec_semantics.py:170: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc] +generics_paramspec_semantics.py:176: error: Incompatible types in assignment (expression has type "ContravariantParamSpecOld[[int]]", variable has type "ContravariantParamSpecOld[[object]]") [assignment] """ -conformance_automated = "Pass" +conformance_automated = "Fail" errors_diff = """ +Line 159: Expected 1 errors +Line 173: Expected 1 errors +Line 177: Expected 1 errors +Line 155: Unexpected errors ['generics_paramspec_semantics.py:155: error: Missing return statement [empty-body]'] +Line 158: Unexpected errors ['generics_paramspec_semantics.py:158: error: Incompatible types in assignment (expression has type "CovariantParamSpec[[int]]", variable has type "CovariantParamSpec[[object]]") [assignment]'] +Line 161: Unexpected errors ['generics_paramspec_semantics.py:161: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]'] +Line 170: Unexpected errors ['generics_paramspec_semantics.py:170: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]'] +Line 176: Unexpected errors ['generics_paramspec_semantics.py:176: error: Incompatible types in assignment (expression has type "ContravariantParamSpecOld[[int]]", variable has type "ContravariantParamSpecOld[[object]]") [assignment]'] """ diff --git a/conformance/results/pyrefly/generics_paramspec_semantics.toml b/conformance/results/pyrefly/generics_paramspec_semantics.toml index a62bb475d..69ae3ffec 100644 --- a/conformance/results/pyrefly/generics_paramspec_semantics.toml +++ b/conformance/results/pyrefly/generics_paramspec_semantics.toml @@ -1,6 +1,17 @@ -conformant = "Pass" -conformance_automated = "Pass" +conformant = "Partial" +conformance_automated = "Fail" errors_diff = """ +Line 151: Expected 1 errors +Line 159: Expected 1 errors +Line 164: Expected 1 errors +Line 168: Expected 1 errors +Line 173: Expected 1 errors +Line 177: Expected 1 errors +Line 150: Unexpected errors ['`ContravariantParamSpec[[object]]` is not assignable to `ContravariantParamSpec[[int]]` [bad-assignment]'] +Line 161: Unexpected errors ['Unexpected keyword argument `contravariant` to ParamSpec [invalid-param-spec]'] +Line 167: Unexpected errors ['`ContravariantParamSpecOld[[object]]` is not assignable to `ContravariantParamSpecOld[[int]]` [bad-assignment]'] +Line 170: Unexpected errors ['Unexpected keyword argument `covariant` to ParamSpec [invalid-param-spec]'] +Line 176: Unexpected errors ['`ContravariantParamSpecOld[[int]]` is not assignable to `ContravariantParamSpecOld[[object]]` [bad-assignment]'] """ output = """ ERROR generics_paramspec_semantics.py:26:4-5: Expected argument `a` to be positional [unexpected-keyword] @@ -14,4 +25,9 @@ ERROR generics_paramspec_semantics.py:120:4-5: Argument `Literal[1]` is not assi ERROR generics_paramspec_semantics.py:127:1-19: Argument `(x: str) -> int` is not assignable to parameter `x` with type `(int, ParamSpec(@_)) -> int` in function `expects_int_first` [bad-argument-type] ERROR generics_paramspec_semantics.py:132:1-19: Argument `(*, x: int) -> int` is not assignable to parameter `x` with type `(int, ParamSpec(@_)) -> int` in function `expects_int_first` [bad-argument-type] ERROR generics_paramspec_semantics.py:137:1-19: Argument `(**kwargs: int) -> int` is not assignable to parameter `x` with type `(int, ParamSpec(@_)) -> int` in function `expects_int_first` [bad-argument-type] +ERROR generics_paramspec_semantics.py:150:39-45: `ContravariantParamSpec[[object]]` is not assignable to `ContravariantParamSpec[[int]]` [bad-assignment] +ERROR generics_paramspec_semantics.py:161:24-42: Unexpected keyword argument `contravariant` to ParamSpec [invalid-param-spec] +ERROR generics_paramspec_semantics.py:167:46-56: `ContravariantParamSpecOld[[object]]` is not assignable to `ContravariantParamSpecOld[[int]]` [bad-assignment] +ERROR generics_paramspec_semantics.py:170:26-40: Unexpected keyword argument `covariant` to ParamSpec [invalid-param-spec] +ERROR generics_paramspec_semantics.py:176:50-61: `ContravariantParamSpecOld[[int]]` is not assignable to `ContravariantParamSpecOld[[object]]` [bad-assignment] """ diff --git a/conformance/results/pyright/generics_paramspec_semantics.toml b/conformance/results/pyright/generics_paramspec_semantics.toml index e24a0a9c8..370ff5ac2 100644 --- a/conformance/results/pyright/generics_paramspec_semantics.toml +++ b/conformance/results/pyright/generics_paramspec_semantics.toml @@ -1,4 +1,4 @@ -conformant = "Pass" +conformant = "Partial" notes = """ Constraint solver doesn't find common type for two signatures captured by a single ParamSpec (allowed). """ @@ -30,7 +30,33 @@ generics_paramspec_semantics.py:132:2 - error: Argument of type "(*, x: int) -> generics_paramspec_semantics.py:137:2 - error: Argument of type "(**kwargs: int) -> int" cannot be assigned to parameter "x" of type "(int, **P@expects_int_first) -> int" in function "expects_int_first" Type "(**kwargs: int) -> int" is not assignable to type "(int, **P@expects_int_first) -> int" Function accepts too many positional parameters; expected 0 but received 1 (reportArgumentType) +generics_paramspec_semantics.py:150:39 - error: Type "ContravariantParamSpec[(object)]" is not assignable to declared type "ContravariantParamSpec[(int)]" + "ContravariantParamSpec[(object)]" is not assignable to "ContravariantParamSpec[(int)]" + Type parameter "InP@ContravariantParamSpec" is invariant, but "(object)" is not the same as "(int)" (reportAssignmentType) +generics_paramspec_semantics.py:158:39 - error: Type "CovariantParamSpec[(int)]" is not assignable to declared type "CovariantParamSpec[(object)]" + "CovariantParamSpec[(int)]" is not assignable to "CovariantParamSpec[(object)]" + Type parameter "OutP@CovariantParamSpec" is invariant, but "(int)" is not the same as "(object)" (reportAssignmentType) +generics_paramspec_semantics.py:161:24 - error: "contravariant" is unknown parameter to ParamSpec (reportGeneralTypeIssues) +generics_paramspec_semantics.py:167:46 - error: Type "ContravariantParamSpecOld[(object)]" is not assignable to declared type "ContravariantParamSpecOld[(int)]" + "ContravariantParamSpecOld[(object)]" is not assignable to "ContravariantParamSpecOld[(int)]" + Type parameter "InP@ContravariantParamSpecOld" is invariant, but "(object)" is not the same as "(int)" (reportAssignmentType) +generics_paramspec_semantics.py:170:26 - error: "covariant" is unknown parameter to ParamSpec (reportGeneralTypeIssues) +generics_paramspec_semantics.py:176:50 - error: Type "ContravariantParamSpecOld[(int)]" is not assignable to declared type "ContravariantParamSpecOld[(object)]" + "ContravariantParamSpecOld[(int)]" is not assignable to "ContravariantParamSpecOld[(object)]" + Type parameter "InP@ContravariantParamSpecOld" is invariant, but "(int)" is not the same as "(object)" (reportAssignmentType) """ -conformance_automated = "Pass" +conformance_automated = "Fail" errors_diff = """ +Line 151: Expected 1 errors +Line 159: Expected 1 errors +Line 164: Expected 1 errors +Line 168: Expected 1 errors +Line 173: Expected 1 errors +Line 177: Expected 1 errors +Line 150: Unexpected errors ['generics_paramspec_semantics.py:150:39 - error: Type "ContravariantParamSpec[(object)]" is not assignable to declared type "ContravariantParamSpec[(int)]"'] +Line 158: Unexpected errors ['generics_paramspec_semantics.py:158:39 - error: Type "CovariantParamSpec[(int)]" is not assignable to declared type "CovariantParamSpec[(object)]"'] +Line 161: Unexpected errors ['generics_paramspec_semantics.py:161:24 - error: "contravariant" is unknown parameter to ParamSpec (reportGeneralTypeIssues)'] +Line 167: Unexpected errors ['generics_paramspec_semantics.py:167:46 - error: Type "ContravariantParamSpecOld[(object)]" is not assignable to declared type "ContravariantParamSpecOld[(int)]"'] +Line 170: Unexpected errors ['generics_paramspec_semantics.py:170:26 - error: "covariant" is unknown parameter to ParamSpec (reportGeneralTypeIssues)'] +Line 176: Unexpected errors ['generics_paramspec_semantics.py:176:50 - error: Type "ContravariantParamSpecOld[(int)]" is not assignable to declared type "ContravariantParamSpecOld[(object)]"'] """ diff --git a/conformance/results/results.html b/conformance/results/results.html index 058d7e553..9524d2dfb 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -293,10 +293,10 @@
Does not reject usage of args/kwargs for out-of-scope ParamSpec
Constraint solver doesn't find common type for two signatures captured by a single ParamSpec (allowed).
Constraint solver doesn't find common type for two signatures captured by a single ParamSpec (allowed).