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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions conformance/results/mypy/generics_paramspec_semantics.toml
Original file line number Diff line number Diff line change
@@ -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]
Expand All @@ -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]']
"""
20 changes: 18 additions & 2 deletions conformance/results/pyrefly/generics_paramspec_semantics.toml
Original file line number Diff line number Diff line change
@@ -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]
Expand All @@ -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]
"""
30 changes: 28 additions & 2 deletions conformance/results/pyright/generics_paramspec_semantics.toml
Original file line number Diff line number Diff line change
@@ -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).
"""
Expand Down Expand Up @@ -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)]"']
"""
8 changes: 4 additions & 4 deletions conformance/results/results.html
Original file line number Diff line number Diff line change
Expand Up @@ -293,10 +293,10 @@ <h3>Python Type System Conformance Test Results</h3>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not reject usage of args/kwargs for out-of-scope ParamSpec</p></span></div></th>
</tr>
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;generics_paramspec_semantics</th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 conformant"><div class="hover-text">Pass*<span class="tooltip-text" id="bottom"><p>Constraint solver doesn't find common type for two signatures captured by a single ParamSpec (allowed).</p></span></div></th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 partially-conformant">Partial</th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Constraint solver doesn't find common type for two signatures captured by a single ParamSpec (allowed).</p></span></div></th>
<th class="column col2 not-conformant">Unknown</th>
<th class="column col2 partially-conformant">Partial</th>
</tr>
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;generics_paramspec_specialization</th>
<th class="column col2 conformant">Pass</th>
Expand Down
18 changes: 17 additions & 1 deletion conformance/results/zuban/generics_paramspec_semantics.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
conformance_automated = "Pass"
conformance_automated = "Fail"
errors_diff = """
Line 151: Expected 1 errors
Line 159: Expected 1 errors
Line 168: 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]']
"""
output = """
generics_paramspec_semantics.py:26: error: Unexpected keyword argument "a" [call-arg]
Expand All @@ -12,4 +22,10 @@ generics_paramspec_semantics.py:120: error: Argument 1 has incompatible type "in
generics_paramspec_semantics.py:127: error: Argument 1 to "expects_int_first" has incompatible type "Callable[[str], int]"; expected "Callable[[int], int]" [arg-type]
generics_paramspec_semantics.py:132: error: Argument 1 to "expects_int_first" has incompatible type "Callable[[NamedArg(int, 'x')], int]"; expected "Callable[[int, Never], int]" [arg-type]
generics_paramspec_semantics.py:137: error: Argument 1 to "expects_int_first" has incompatible type "Callable[[KwArg(int)], int]"; expected "Callable[[int, Never], int]" [arg-type]
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: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]
"""
33 changes: 33 additions & 0 deletions conformance/tests/generics_paramspec_semantics.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,36 @@ def three(**kwargs: int) -> int:
@expects_int_first # OK
def four(*args: int) -> int:
raise NotImplementedError

class ContravariantParamSpec[**InP]:
def f(self, *args: InP.args, **kwargs: InP.kwargs): ...

in_obj = ContravariantParamSpec[object]()
in_int: ContravariantParamSpec[int] = in_obj # OK
in_obj = in_int # E


class CovariantParamSpec[**OutP]:
def f(self) -> Callable[OutP, None]: ...

out_int = CovariantParamSpec[int]()
out_obj: CovariantParamSpec[object] = out_int # OK
out_int = out_obj # E

InP = ParamSpec("InP", contravariant=True)

class ContravariantParamSpecOld(Generic[InP]):
def f(self) -> Callable[InP, None]: ... # E

in_obj_old = ContravariantParamSpecOld[object]()
in_int_old: ContravariantParamSpecOld[int] = in_obj_old # OK
in_obj_old = in_int_old # E

OutP = ParamSpec("OutP", covariant=True)

class CovariantParamSpecOld(Generic[OutP]):
def f(self, *args: OutP.args, **kwargs: OutP.kwargs): ... # E

out_int_old = ContravariantParamSpecOld[int]()
out_obj_old: ContravariantParamSpecOld[object] = out_int_old # OK
out_int_old = out_obj_old # E
5 changes: 2 additions & 3 deletions docs/spec/generics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2729,9 +2729,8 @@ The algorithm for computing the variance of a type parameter is as follows.

For each type parameter in a generic class:

1. If the type parameter is variadic (``TypeVarTuple``) or a parameter
specification (``ParamSpec``), it is always considered invariant. No further
inference is needed.
1. If the type parameter is variadic (``TypeVarTuple``) it is always
considered invariant. No further inference is needed.

2. If the type parameter comes from a traditional ``TypeVar`` declaration and
is not specified as ``infer_variance`` (see below), its variance is specified
Expand Down