Skip to content

Commit 117964e

Browse files
committed
specify that parameter specification should have variance
1 parent fecce0d commit 117964e

File tree

8 files changed

+197
-6
lines changed

8 files changed

+197
-6
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
conformant = "Unsupported"
2+
conformance_automated = "Fail"
3+
errors_diff = """
4+
Line 24: Expected 1 errors
5+
Line 31: Expected 1 errors
6+
Line 47: Expected 1 errors
7+
Line 23: Unexpected errors ['generics_paramspec_variance.py:23: error: Incompatible types in assignment (expression has type "CovariantParamSpec[[int]]", variable has type "CovariantParamSpec[[object]]") [assignment]']
8+
Line 26: Unexpected errors ['generics_paramspec_variance.py:26: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]']
9+
Line 30: Unexpected errors ['generics_paramspec_variance.py:30: error: Missing return statement [empty-body]']
10+
Line 37: Unexpected errors ['generics_paramspec_variance.py:37: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]']
11+
Line 46: Unexpected errors ['generics_paramspec_variance.py:46: error: Incompatible types in assignment (expression has type "CovariantParamSpecOld[[int]]", variable has type "CovariantParamSpecOld[[object]]") [assignment]']
12+
"""
13+
output = """
14+
generics_paramspec_variance.py:15: error: Incompatible types in assignment (expression has type "ContravariantParamSpec[[int]]", variable has type "ContravariantParamSpec[[object]]") [assignment]
15+
generics_paramspec_variance.py:23: error: Incompatible types in assignment (expression has type "CovariantParamSpec[[int]]", variable has type "CovariantParamSpec[[object]]") [assignment]
16+
generics_paramspec_variance.py:26: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]
17+
generics_paramspec_variance.py:30: error: Missing return statement [empty-body]
18+
generics_paramspec_variance.py:35: error: Incompatible types in assignment (expression has type "ContravariantParamSpecOld[[int]]", variable has type "ContravariantParamSpecOld[[object]]") [assignment]
19+
generics_paramspec_variance.py:37: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]
20+
generics_paramspec_variance.py:41: error: Missing return statement [empty-body]
21+
generics_paramspec_variance.py:46: error: Incompatible types in assignment (expression has type "CovariantParamSpecOld[[int]]", variable has type "CovariantParamSpecOld[[object]]") [assignment]
22+
"""
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
conformant = "Unsupported"
2+
conformance_automated = "Fail"
3+
errors_diff = """
4+
Line 15: Expected 1 errors
5+
Line 24: Expected 1 errors
6+
Line 31: Expected 1 errors
7+
Line 41: Expected 1 errors
8+
Line 14: Unexpected errors ['`ContravariantParamSpec[[object]]` is not assignable to `ContravariantParamSpec[[int]]` [bad-assignment]']
9+
Line 23: Unexpected errors ['`CovariantParamSpec[[int]]` is not assignable to `CovariantParamSpec[[object]]` [bad-assignment]']
10+
Line 26: Unexpected errors ['Unexpected keyword argument `contravariant` to ParamSpec [invalid-param-spec]']
11+
Line 34: Unexpected errors ['`ContravariantParamSpecOld[[object]]` is not assignable to `ContravariantParamSpecOld[[int]]` [bad-assignment]']
12+
Line 37: Unexpected errors ['Unexpected keyword argument `covariant` to ParamSpec [invalid-param-spec]']
13+
Line 46: Unexpected errors ['`CovariantParamSpecOld[[int]]` is not assignable to `CovariantParamSpecOld[[object]]` [bad-assignment]']
14+
"""
15+
output = """
16+
ERROR generics_paramspec_variance.py:14:39-45: `ContravariantParamSpec[[object]]` is not assignable to `ContravariantParamSpec[[int]]` [bad-assignment]
17+
ERROR generics_paramspec_variance.py:23:39-46: `CovariantParamSpec[[int]]` is not assignable to `CovariantParamSpec[[object]]` [bad-assignment]
18+
ERROR generics_paramspec_variance.py:26:24-42: Unexpected keyword argument `contravariant` to ParamSpec [invalid-param-spec]
19+
ERROR generics_paramspec_variance.py:34:46-56: `ContravariantParamSpecOld[[object]]` is not assignable to `ContravariantParamSpecOld[[int]]` [bad-assignment]
20+
ERROR generics_paramspec_variance.py:35:14-24: `ContravariantParamSpecOld[[int]]` is not assignable to variable `in_obj_old` with type `ContravariantParamSpecOld[[object]]` [bad-assignment]
21+
ERROR generics_paramspec_variance.py:37:26-40: Unexpected keyword argument `covariant` to ParamSpec [invalid-param-spec]
22+
ERROR generics_paramspec_variance.py:46:46-57: `CovariantParamSpecOld[[int]]` is not assignable to `CovariantParamSpecOld[[object]]` [bad-assignment]
23+
ERROR generics_paramspec_variance.py:47:15-26: `CovariantParamSpecOld[[object]]` is not assignable to variable `out_int_old` with type `CovariantParamSpecOld[[int]]` [bad-assignment]
24+
"""
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
conformant = "Unsupported"
2+
conformance_automated = "Fail"
3+
errors_diff = """
4+
Line 31: Expected 1 errors
5+
Line 41: Expected 1 errors
6+
Line 14: Unexpected errors ['generics_paramspec_variance.py:14:39 - error: Type "ContravariantParamSpec[(object)]" is not assignable to declared type "ContravariantParamSpec[(int)]"']
7+
Line 23: Unexpected errors ['generics_paramspec_variance.py:23:39 - error: Type "CovariantParamSpec[(int)]" is not assignable to declared type "CovariantParamSpec[(object)]"']
8+
Line 26: Unexpected errors ['generics_paramspec_variance.py:26:24 - error: "contravariant" is unknown parameter to ParamSpec (reportGeneralTypeIssues)']
9+
Line 34: Unexpected errors ['generics_paramspec_variance.py:34:46 - error: Type "ContravariantParamSpecOld[(object)]" is not assignable to declared type "ContravariantParamSpecOld[(int)]"']
10+
Line 37: Unexpected errors ['generics_paramspec_variance.py:37:26 - error: "covariant" is unknown parameter to ParamSpec (reportGeneralTypeIssues)']
11+
Line 46: Unexpected errors ['generics_paramspec_variance.py:46:46 - error: Type "CovariantParamSpecOld[(int)]" is not assignable to declared type "CovariantParamSpecOld[(object)]"']
12+
"""
13+
output = """
14+
generics_paramspec_variance.py:14:39 - error: Type "ContravariantParamSpec[(object)]" is not assignable to declared type "ContravariantParamSpec[(int)]"
15+
  "ContravariantParamSpec[(object)]" is not assignable to "ContravariantParamSpec[(int)]"
16+
    Type parameter "InP@ContravariantParamSpec" is invariant, but "(object)" is not the same as "(int)" (reportAssignmentType)
17+
generics_paramspec_variance.py:15:10 - error: Type "ContravariantParamSpec[(int)]" is not assignable to declared type "ContravariantParamSpec[(object)]"
18+
  "ContravariantParamSpec[(int)]" is not assignable to "ContravariantParamSpec[(object)]"
19+
    Type parameter "InP@ContravariantParamSpec" is invariant, but "(int)" is not the same as "(object)" (reportAssignmentType)
20+
generics_paramspec_variance.py:23:39 - error: Type "CovariantParamSpec[(int)]" is not assignable to declared type "CovariantParamSpec[(object)]"
21+
  "CovariantParamSpec[(int)]" is not assignable to "CovariantParamSpec[(object)]"
22+
    Type parameter "OutP@CovariantParamSpec" is invariant, but "(int)" is not the same as "(object)" (reportAssignmentType)
23+
generics_paramspec_variance.py:24:11 - error: Type "CovariantParamSpec[(object)]" is not assignable to declared type "CovariantParamSpec[(int)]"
24+
  "CovariantParamSpec[(object)]" is not assignable to "CovariantParamSpec[(int)]"
25+
    Type parameter "OutP@CovariantParamSpec" is invariant, but "(object)" is not the same as "(int)" (reportAssignmentType)
26+
generics_paramspec_variance.py:26:24 - error: "contravariant" is unknown parameter to ParamSpec (reportGeneralTypeIssues)
27+
generics_paramspec_variance.py:34:46 - error: Type "ContravariantParamSpecOld[(object)]" is not assignable to declared type "ContravariantParamSpecOld[(int)]"
28+
  "ContravariantParamSpecOld[(object)]" is not assignable to "ContravariantParamSpecOld[(int)]"
29+
    Type parameter "InP@ContravariantParamSpecOld" is invariant, but "(object)" is not the same as "(int)" (reportAssignmentType)
30+
generics_paramspec_variance.py:35:14 - error: Type "ContravariantParamSpecOld[(int)]" is not assignable to declared type "ContravariantParamSpecOld[(object)]"
31+
  "ContravariantParamSpecOld[(int)]" is not assignable to "ContravariantParamSpecOld[(object)]"
32+
    Type parameter "InP@ContravariantParamSpecOld" is invariant, but "(int)" is not the same as "(object)" (reportAssignmentType)
33+
generics_paramspec_variance.py:37:26 - error: "covariant" is unknown parameter to ParamSpec (reportGeneralTypeIssues)
34+
generics_paramspec_variance.py:46:46 - error: Type "CovariantParamSpecOld[(int)]" is not assignable to declared type "CovariantParamSpecOld[(object)]"
35+
  "CovariantParamSpecOld[(int)]" is not assignable to "CovariantParamSpecOld[(object)]"
36+
    Type parameter "OutP@CovariantParamSpecOld" is invariant, but "(int)" is not the same as "(object)" (reportAssignmentType)
37+
generics_paramspec_variance.py:47:15 - error: Type "CovariantParamSpecOld[(object)]" is not assignable to declared type "CovariantParamSpecOld[(int)]"
38+
  "CovariantParamSpecOld[(object)]" is not assignable to "CovariantParamSpecOld[(int)]"
39+
    Type parameter "OutP@CovariantParamSpecOld" is invariant, but "(object)" is not the same as "(int)" (reportAssignmentType)
40+
"""

conformance/results/results.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,13 @@ <h3>Python Type System Conformance Test Results</h3>
335335
<th class="column col2 conformant">Pass</th>
336336
<th class="column col2 conformant">Pass</th>
337337
</tr>
338+
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;generics_paramspec_variance</th>
339+
<th class="column col2 not-conformant">Unsupported</th>
340+
<th class="column col2 not-conformant">Unsupported</th>
341+
<th class="column col2 not-conformant">Unsupported</th>
342+
<th class="column col2 not-conformant">Unsupported</th>
343+
<th class="column col2 not-conformant">Unsupported</th>
344+
</tr>
338345
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;generics_scoping</th>
339346
<th class="column col2 conformant">Pass</th>
340347
<th class="column col2 conformant">Pass</th>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
conformant = "Unsupported"
2+
conformance_automated = "Fail"
3+
errors_diff = """
4+
Line 15: Expected 1 errors
5+
Line 24: Expected 1 errors
6+
Line 35: Expected 1 errors
7+
Line 47: Expected 1 errors
8+
Line 26: Unexpected errors ['generics_paramspec_variance.py:26:7: error[invalid-paramspec] The variance and bound arguments for `ParamSpec` do not have defined semantics yet']
9+
Line 29: Unexpected errors ['generics_paramspec_variance.py:29:33: error[invalid-argument-type] `ParamSpec` is not a valid argument to `Generic`']
10+
Line 30: Unexpected errors ['generics_paramspec_variance.py:30:23: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `(...) -> Unknown`', 'generics_paramspec_variance.py:30:32: error[invalid-type-form] Variable of type `ParamSpec` is not allowed in a return type annotation', 'generics_paramspec_variance.py:30:32: error[invalid-type-form] The first argument to `Callable` must be either a list of types, ParamSpec, Concatenate, or `...`']
11+
Line 37: Unexpected errors ['generics_paramspec_variance.py:37:8: error[invalid-paramspec] The variance and bound arguments for `ParamSpec` do not have defined semantics yet']
12+
Line 40: Unexpected errors ['generics_paramspec_variance.py:40:29: error[invalid-argument-type] `ParamSpec` is not a valid argument to `Generic`']
13+
Line 42: Unexpected errors ['generics_paramspec_variance.py:42:34: error[invalid-type-form] Variable of type `ParamSpec` is not allowed in a parameter annotation', 'generics_paramspec_variance.py:42:34: error[invalid-type-form] The first argument to `Callable` must be either a list of types, ParamSpec, Concatenate, or `...`']
14+
"""
15+
output = """
16+
generics_paramspec_variance.py:26:7: error[invalid-paramspec] The variance and bound arguments for `ParamSpec` do not have defined semantics yet
17+
generics_paramspec_variance.py:29:33: error[invalid-argument-type] `ParamSpec` is not a valid argument to `Generic`
18+
generics_paramspec_variance.py:30:23: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `(...) -> Unknown`
19+
generics_paramspec_variance.py:30:32: error[invalid-type-form] Variable of type `ParamSpec` is not allowed in a return type annotation
20+
generics_paramspec_variance.py:30:32: error[invalid-type-form] The first argument to `Callable` must be either a list of types, ParamSpec, Concatenate, or `...`
21+
generics_paramspec_variance.py:31:34: error[invalid-type-form] Variable of type `ParamSpec` is not allowed in a parameter annotation
22+
generics_paramspec_variance.py:31:34: error[invalid-type-form] The first argument to `Callable` must be either a list of types, ParamSpec, Concatenate, or `...`
23+
generics_paramspec_variance.py:37:8: error[invalid-paramspec] The variance and bound arguments for `ParamSpec` do not have defined semantics yet
24+
generics_paramspec_variance.py:40:29: error[invalid-argument-type] `ParamSpec` is not a valid argument to `Generic`
25+
generics_paramspec_variance.py:41:23: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `(...) -> Unknown`
26+
generics_paramspec_variance.py:41:32: error[invalid-type-form] Variable of type `ParamSpec` is not allowed in a return type annotation
27+
generics_paramspec_variance.py:41:32: error[invalid-type-form] The first argument to `Callable` must be either a list of types, ParamSpec, Concatenate, or `...`
28+
generics_paramspec_variance.py:42:34: error[invalid-type-form] Variable of type `ParamSpec` is not allowed in a parameter annotation
29+
generics_paramspec_variance.py:42:34: error[invalid-type-form] The first argument to `Callable` must be either a list of types, ParamSpec, Concatenate, or `...`
30+
"""
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
conformant = "Unsupported"
2+
conformance_automated = "Fail"
3+
errors_diff = """
4+
Line 24: Expected 1 errors
5+
Line 31: Expected 1 errors
6+
Line 47: Expected 1 errors
7+
Line 23: Unexpected errors ['generics_paramspec_variance.py:23: error: Incompatible types in assignment (expression has type "CovariantParamSpec[[int]]", variable has type "CovariantParamSpec[[object]]") [assignment]']
8+
Line 26: Unexpected errors ['generics_paramspec_variance.py:26: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]']
9+
Line 30: Unexpected errors ['generics_paramspec_variance.py:30: error: Missing return statement [empty-body]']
10+
Line 37: Unexpected errors ['generics_paramspec_variance.py:37: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]']
11+
Line 46: Unexpected errors ['generics_paramspec_variance.py:46: error: Incompatible types in assignment (expression has type "CovariantParamSpecOld[[int]]", variable has type "CovariantParamSpecOld[[object]]") [assignment]']
12+
"""
13+
output = """
14+
generics_paramspec_variance.py:15: error: Incompatible types in assignment (expression has type "ContravariantParamSpec[[int]]", variable has type "ContravariantParamSpec[[object]]") [assignment]
15+
generics_paramspec_variance.py:23: error: Incompatible types in assignment (expression has type "CovariantParamSpec[[int]]", variable has type "CovariantParamSpec[[object]]") [assignment]
16+
generics_paramspec_variance.py:26: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]
17+
generics_paramspec_variance.py:30: error: Missing return statement [empty-body]
18+
generics_paramspec_variance.py:35: error: Incompatible types in assignment (expression has type "ContravariantParamSpecOld[[int]]", variable has type "ContravariantParamSpecOld[[object]]") [assignment]
19+
generics_paramspec_variance.py:37: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]
20+
generics_paramspec_variance.py:41: error: Missing return statement [empty-body]
21+
generics_paramspec_variance.py:46: error: Incompatible types in assignment (expression has type "CovariantParamSpecOld[[int]]", variable has type "CovariantParamSpecOld[[object]]") [assignment]
22+
"""
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""
2+
Tests variance of ParamSpec.
3+
"""
4+
5+
# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#semantics
6+
7+
8+
from typing import Callable, Generic, ParamSpec
9+
10+
class ContravariantParamSpec[**InP]:
11+
def f(self, *args: InP.args, **kwargs: InP.kwargs): ...
12+
13+
in_obj: ContravariantParamSpec[object] = ContravariantParamSpec()
14+
in_int: ContravariantParamSpec[int] = in_obj # OK
15+
in_obj = in_int # E
16+
17+
18+
class CovariantParamSpec[**OutP]:
19+
def f(self, fn: Callable[OutP, None]) -> None: ...
20+
21+
22+
out_int: CovariantParamSpec[int] = CovariantParamSpec()
23+
out_obj: CovariantParamSpec[object] = out_int # OK
24+
out_int = out_obj # E
25+
26+
InP = ParamSpec("InP", contravariant=True)
27+
28+
29+
class ContravariantParamSpecOld(Generic[InP]):
30+
def in_f(self) -> Callable[InP, None]: ... # OK
31+
def out_f(self, fn: Callable[InP, None]) -> None: ... # E
32+
33+
in_obj_old: ContravariantParamSpecOld[object] = ContravariantParamSpecOld()
34+
in_int_old: ContravariantParamSpecOld[int] = in_obj_old # OK
35+
in_obj_old = in_int_old # E
36+
37+
OutP = ParamSpec("OutP", covariant=True)
38+
39+
40+
class CovariantParamSpecOld(Generic[OutP]):
41+
def in_f(self) -> Callable[OutP, None]: ... # E
42+
def out_f(self, fn: Callable[OutP, None]) -> None: ... # OK
43+
44+
45+
out_int_old: CovariantParamSpecOld[int] = CovariantParamSpecOld()
46+
out_obj_old: CovariantParamSpecOld[object] = out_int_old # OK
47+
out_int_old = out_obj_old # E

docs/spec/generics.rst

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2712,13 +2712,12 @@ The algorithm for computing the variance of a type parameter is as follows.
27122712

27132713
For each type parameter in a generic class:
27142714

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

2719-
2. If the type parameter comes from a traditional ``TypeVar`` declaration and
2720-
is not specified as ``infer_variance`` (see below), its variance is specified
2721-
by the ``TypeVar`` constructor call. No further inference is needed.
2718+
2. If the type parameter comes from a traditional ``TypeVar``/``ParamSpec``
2719+
declaration and is not specified as ``infer_variance`` (see below), its
2720+
variance is specified by the constructor call. No further inference is needed.
27222721

27232722
3. Create two specialized versions of the class. We'll refer to these as
27242723
``upper`` and ``lower`` specializations. In both of these specializations,

0 commit comments

Comments
 (0)