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
22 changes: 22 additions & 0 deletions conformance/results/mypy/generics_paramspec_variance.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
conformant = "Unsupported"
conformance_automated = "Fail"
errors_diff = """
Line 24: Expected 1 errors
Line 31: Expected 1 errors
Line 47: Expected 1 errors
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]']
Line 26: Unexpected errors ['generics_paramspec_variance.py:26: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]']
Line 30: Unexpected errors ['generics_paramspec_variance.py:30: error: Missing return statement [empty-body]']
Line 37: Unexpected errors ['generics_paramspec_variance.py:37: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]']
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]']
"""
output = """
generics_paramspec_variance.py:15: error: Incompatible types in assignment (expression has type "ContravariantParamSpec[[int]]", variable has type "ContravariantParamSpec[[object]]") [assignment]
generics_paramspec_variance.py:23: error: Incompatible types in assignment (expression has type "CovariantParamSpec[[int]]", variable has type "CovariantParamSpec[[object]]") [assignment]
generics_paramspec_variance.py:26: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]
generics_paramspec_variance.py:30: error: Missing return statement [empty-body]
generics_paramspec_variance.py:35: error: Incompatible types in assignment (expression has type "ContravariantParamSpecOld[[int]]", variable has type "ContravariantParamSpecOld[[object]]") [assignment]
generics_paramspec_variance.py:37: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]
generics_paramspec_variance.py:41: error: Missing return statement [empty-body]
generics_paramspec_variance.py:46: error: Incompatible types in assignment (expression has type "CovariantParamSpecOld[[int]]", variable has type "CovariantParamSpecOld[[object]]") [assignment]
"""
24 changes: 24 additions & 0 deletions conformance/results/pyrefly/generics_paramspec_variance.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
conformant = "Unsupported"
conformance_automated = "Fail"
errors_diff = """
Line 15: Expected 1 errors
Line 24: Expected 1 errors
Line 31: Expected 1 errors
Line 41: Expected 1 errors
Line 14: Unexpected errors ['`ContravariantParamSpec[[object]]` is not assignable to `ContravariantParamSpec[[int]]` [bad-assignment]']
Line 23: Unexpected errors ['`CovariantParamSpec[[int]]` is not assignable to `CovariantParamSpec[[object]]` [bad-assignment]']
Line 26: Unexpected errors ['Unexpected keyword argument `contravariant` to ParamSpec [invalid-param-spec]']
Line 34: Unexpected errors ['`ContravariantParamSpecOld[[object]]` is not assignable to `ContravariantParamSpecOld[[int]]` [bad-assignment]']
Line 37: Unexpected errors ['Unexpected keyword argument `covariant` to ParamSpec [invalid-param-spec]']
Line 46: Unexpected errors ['`CovariantParamSpecOld[[int]]` is not assignable to `CovariantParamSpecOld[[object]]` [bad-assignment]']
"""
output = """
ERROR generics_paramspec_variance.py:14:39-45: `ContravariantParamSpec[[object]]` is not assignable to `ContravariantParamSpec[[int]]` [bad-assignment]
ERROR generics_paramspec_variance.py:23:39-46: `CovariantParamSpec[[int]]` is not assignable to `CovariantParamSpec[[object]]` [bad-assignment]
ERROR generics_paramspec_variance.py:26:24-42: Unexpected keyword argument `contravariant` to ParamSpec [invalid-param-spec]
ERROR generics_paramspec_variance.py:34:46-56: `ContravariantParamSpecOld[[object]]` is not assignable to `ContravariantParamSpecOld[[int]]` [bad-assignment]
ERROR generics_paramspec_variance.py:35:14-24: `ContravariantParamSpecOld[[int]]` is not assignable to variable `in_obj_old` with type `ContravariantParamSpecOld[[object]]` [bad-assignment]
ERROR generics_paramspec_variance.py:37:26-40: Unexpected keyword argument `covariant` to ParamSpec [invalid-param-spec]
ERROR generics_paramspec_variance.py:46:46-57: `CovariantParamSpecOld[[int]]` is not assignable to `CovariantParamSpecOld[[object]]` [bad-assignment]
ERROR generics_paramspec_variance.py:47:15-26: `CovariantParamSpecOld[[object]]` is not assignable to variable `out_int_old` with type `CovariantParamSpecOld[[int]]` [bad-assignment]
"""
40 changes: 40 additions & 0 deletions conformance/results/pyright/generics_paramspec_variance.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
conformant = "Unsupported"
conformance_automated = "Fail"
errors_diff = """
Line 31: Expected 1 errors
Line 41: Expected 1 errors
Line 14: Unexpected errors ['generics_paramspec_variance.py:14:39 - error: Type "ContravariantParamSpec[(object)]" is not assignable to declared type "ContravariantParamSpec[(int)]"']
Line 23: Unexpected errors ['generics_paramspec_variance.py:23:39 - error: Type "CovariantParamSpec[(int)]" is not assignable to declared type "CovariantParamSpec[(object)]"']
Line 26: Unexpected errors ['generics_paramspec_variance.py:26:24 - error: "contravariant" is unknown parameter to ParamSpec (reportGeneralTypeIssues)']
Line 34: Unexpected errors ['generics_paramspec_variance.py:34:46 - error: Type "ContravariantParamSpecOld[(object)]" is not assignable to declared type "ContravariantParamSpecOld[(int)]"']
Line 37: Unexpected errors ['generics_paramspec_variance.py:37:26 - error: "covariant" is unknown parameter to ParamSpec (reportGeneralTypeIssues)']
Line 46: Unexpected errors ['generics_paramspec_variance.py:46:46 - error: Type "CovariantParamSpecOld[(int)]" is not assignable to declared type "CovariantParamSpecOld[(object)]"']
"""
output = """
generics_paramspec_variance.py:14: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_variance.py:15:10 - error: Type "ContravariantParamSpec[(int)]" is not assignable to declared type "ContravariantParamSpec[(object)]"
  "ContravariantParamSpec[(int)]" is not assignable to "ContravariantParamSpec[(object)]"
    Type parameter "InP@ContravariantParamSpec" is invariant, but "(int)" is not the same as "(object)" (reportAssignmentType)
generics_paramspec_variance.py:23: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_variance.py:24:11 - error: Type "CovariantParamSpec[(object)]" is not assignable to declared type "CovariantParamSpec[(int)]"
  "CovariantParamSpec[(object)]" is not assignable to "CovariantParamSpec[(int)]"
    Type parameter "OutP@CovariantParamSpec" is invariant, but "(object)" is not the same as "(int)" (reportAssignmentType)
generics_paramspec_variance.py:26:24 - error: "contravariant" is unknown parameter to ParamSpec (reportGeneralTypeIssues)
generics_paramspec_variance.py:34: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_variance.py:35:14 - 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)
generics_paramspec_variance.py:37:26 - error: "covariant" is unknown parameter to ParamSpec (reportGeneralTypeIssues)
generics_paramspec_variance.py:46:46 - error: Type "CovariantParamSpecOld[(int)]" is not assignable to declared type "CovariantParamSpecOld[(object)]"
  "CovariantParamSpecOld[(int)]" is not assignable to "CovariantParamSpecOld[(object)]"
    Type parameter "OutP@CovariantParamSpecOld" is invariant, but "(int)" is not the same as "(object)" (reportAssignmentType)
generics_paramspec_variance.py:47:15 - error: Type "CovariantParamSpecOld[(object)]" is not assignable to declared type "CovariantParamSpecOld[(int)]"
  "CovariantParamSpecOld[(object)]" is not assignable to "CovariantParamSpecOld[(int)]"
    Type parameter "OutP@CovariantParamSpecOld" is invariant, but "(object)" is not the same as "(int)" (reportAssignmentType)
"""
7 changes: 7 additions & 0 deletions conformance/results/results.html
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,13 @@ <h3>Python Type System Conformance Test Results</h3>
<th class="column col2 conformant">Pass</th>
<th class="column col2 conformant">Pass</th>
</tr>
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;generics_paramspec_variance</th>
<th class="column col2 not-conformant">Unsupported</th>
<th class="column col2 not-conformant">Unsupported</th>
<th class="column col2 not-conformant">Unsupported</th>
<th class="column col2 not-conformant">Unsupported</th>
<th class="column col2 not-conformant">Unsupported</th>
</tr>
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;generics_scoping</th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 conformant">Pass</th>
Expand Down
30 changes: 30 additions & 0 deletions conformance/results/ty/generics_paramspec_variance.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
conformant = "Unsupported"
conformance_automated = "Fail"
errors_diff = """
Line 15: Expected 1 errors
Line 24: Expected 1 errors
Line 35: Expected 1 errors
Line 47: Expected 1 errors
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']
Line 29: Unexpected errors ['generics_paramspec_variance.py:29:33: error[invalid-argument-type] `ParamSpec` is not a valid argument to `Generic`']
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 `...`']
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']
Line 40: Unexpected errors ['generics_paramspec_variance.py:40:29: error[invalid-argument-type] `ParamSpec` is not a valid argument to `Generic`']
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 `...`']
"""
output = """
generics_paramspec_variance.py:26:7: error[invalid-paramspec] The variance and bound arguments for `ParamSpec` do not have defined semantics yet
generics_paramspec_variance.py:29:33: error[invalid-argument-type] `ParamSpec` is not a valid argument to `Generic`
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 `...`
generics_paramspec_variance.py:31:34: error[invalid-type-form] Variable of type `ParamSpec` is not allowed in a parameter annotation
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 `...`
generics_paramspec_variance.py:37:8: error[invalid-paramspec] The variance and bound arguments for `ParamSpec` do not have defined semantics yet
generics_paramspec_variance.py:40:29: error[invalid-argument-type] `ParamSpec` is not a valid argument to `Generic`
generics_paramspec_variance.py:41:23: error[empty-body] Function always implicitly returns `None`, which is not assignable to return type `(...) -> Unknown`
generics_paramspec_variance.py:41:32: error[invalid-type-form] Variable of type `ParamSpec` is not allowed in a return type annotation
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 `...`
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 `...`
"""
22 changes: 22 additions & 0 deletions conformance/results/zuban/generics_paramspec_variance.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
conformant = "Unsupported"
conformance_automated = "Fail"
errors_diff = """
Line 24: Expected 1 errors
Line 31: Expected 1 errors
Line 47: Expected 1 errors
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]']
Line 26: Unexpected errors ['generics_paramspec_variance.py:26: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]']
Line 30: Unexpected errors ['generics_paramspec_variance.py:30: error: Missing return statement [empty-body]']
Line 37: Unexpected errors ['generics_paramspec_variance.py:37: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]']
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]']
"""
output = """
generics_paramspec_variance.py:15: error: Incompatible types in assignment (expression has type "ContravariantParamSpec[[int]]", variable has type "ContravariantParamSpec[[object]]") [assignment]
generics_paramspec_variance.py:23: error: Incompatible types in assignment (expression has type "CovariantParamSpec[[int]]", variable has type "CovariantParamSpec[[object]]") [assignment]
generics_paramspec_variance.py:26: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]
generics_paramspec_variance.py:30: error: Missing return statement [empty-body]
generics_paramspec_variance.py:35: error: Incompatible types in assignment (expression has type "ContravariantParamSpecOld[[int]]", variable has type "ContravariantParamSpecOld[[object]]") [assignment]
generics_paramspec_variance.py:37: error: The variance and bound arguments to ParamSpec do not have defined semantics yet [misc]
generics_paramspec_variance.py:41: error: Missing return statement [empty-body]
generics_paramspec_variance.py:46: error: Incompatible types in assignment (expression has type "CovariantParamSpecOld[[int]]", variable has type "CovariantParamSpecOld[[object]]") [assignment]
"""
47 changes: 47 additions & 0 deletions conformance/tests/generics_paramspec_variance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""
Tests variance of ParamSpec.
"""

# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#semantics


from typing import Callable, Generic, ParamSpec

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

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


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


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

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


class ContravariantParamSpecOld(Generic[InP]):
def in_f(self) -> Callable[InP, None]: ... # OK
def out_f(self, fn: Callable[InP, None]) -> None: ... # E

in_obj_old: ContravariantParamSpecOld[object] = ContravariantParamSpecOld()
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 in_f(self) -> Callable[OutP, None]: ... # E
def out_f(self, fn: Callable[OutP, None]) -> None: ... # OK


out_int_old: CovariantParamSpecOld[int] = CovariantParamSpecOld()
out_obj_old: CovariantParamSpecOld[object] = out_int_old # OK
out_int_old = out_obj_old # E
11 changes: 5 additions & 6 deletions docs/spec/generics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2712,13 +2712,12 @@ 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
by the ``TypeVar`` constructor call. No further inference is needed.
2. If the type parameter comes from a traditional ``TypeVar``/``ParamSpec``
declaration and is not specified as ``infer_variance`` (see below), its
variance is specified by the constructor call. No further inference is needed.

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