From 36e8af7166206c888bf8a1173531edb78291598b Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 29 Sep 2021 11:42:07 +0300 Subject: [PATCH 1/3] Fixes type vars semanal with `ParamSpec`, refs #11218 --- mypy/semanal.py | 10 +++++----- test-data/unit/semanal-errors.test | 29 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 7bfa3c66e118..55564306dbb8 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -91,7 +91,7 @@ FunctionLike, UnboundType, TypeVarType, TupleType, UnionType, StarType, CallableType, Overloaded, Instance, Type, AnyType, LiteralType, LiteralValue, TypeTranslator, TypeOfAny, TypeType, NoneType, PlaceholderType, TPDICT_NAMES, ProperType, - get_proper_type, get_proper_types, TypeAliasType + get_proper_type, get_proper_types, TypeAliasType, ) from mypy.typeops import function_type from mypy.type_visitor import TypeQuery @@ -1326,10 +1326,10 @@ class Foo(Bar, Generic[T]): ... tvar_defs: List[TypeVarType] = [] for name, tvar_expr in declared_tvars: tvar_def = self.tvar_scope.bind_new(name, tvar_expr) - assert isinstance(tvar_def, TypeVarType), ( - "mypy does not currently support ParamSpec use in generic classes" - ) - tvar_defs.append(tvar_def) + if isinstance(tvar_def, TypeVarType): + # This can also be `ParamSpecType`, + # error will be reported elsewhere: #11218 + tvar_defs.append(tvar_def) return base_type_exprs, tvar_defs, is_protocol def analyze_class_typevar_declaration( diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 9dc75a4930e4..29e44bf9f5e7 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -41,6 +41,35 @@ x = None # type: X [out] main:2: error: Name "X" is not defined +[case testInvalidParamSpecType1] +# flags: --python-version 3.10 +from typing import ParamSpec + +P = ParamSpec("P") + +class MyFunction(P): + ... + +a: MyFunction[int] +[out] +main:6: error: Invalid location for ParamSpec "P" +main:6: note: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]' +main:9: error: "MyFunction" expects no type arguments, but 1 given + +[case testInvalidParamSpecType2] +from typing_extensions import ParamSpec + +P = ParamSpec("P") + +class MyFunction(P): + ... + +a: MyFunction[int] +[out] +main:5: error: Invalid location for ParamSpec "P" +main:5: note: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]' +main:8: error: "MyFunction" expects no type arguments, but 1 given + [case testInvalidGenericArg] from typing import TypeVar, Generic t = TypeVar('t') From d3256debfee0e819124bb20e4606b104a9f8b72a Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 29 Sep 2021 21:14:44 +0300 Subject: [PATCH 2/3] Addresses review --- test-data/unit/semanal-errors.test | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 29e44bf9f5e7..3a76c26b8bb9 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -70,6 +70,20 @@ main:5: error: Invalid location for ParamSpec "P" main:5: note: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]' main:8: error: "MyFunction" expects no type arguments, but 1 given +[case testInvalidParamSpecType3] +# flags: --python-version 3.10 +from typing import Generic, TypeVar, Callable, ParamSpec + +T = TypeVar("T") +P = ParamSpec("P") + +class X(Generic[T, P]): + f: Callable[P, int] + x: T +[out] +main:7: error: Free type variable expected in Generic[...] +main:8: error: The first argument to Callable must be a list of types or "..." + [case testInvalidGenericArg] from typing import TypeVar, Generic t = TypeVar('t') From e4643189eda1ec046a107ade9c863c76b7433200 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 29 Sep 2021 12:13:58 -0700 Subject: [PATCH 3/3] Update test-data/unit/semanal-errors.test --- test-data/unit/semanal-errors.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 3a76c26b8bb9..62ffb4e62b07 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -70,7 +70,7 @@ main:5: error: Invalid location for ParamSpec "P" main:5: note: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]' main:8: error: "MyFunction" expects no type arguments, but 1 given -[case testInvalidParamSpecType3] +[case testGenericParamSpec] # flags: --python-version 3.10 from typing import Generic, TypeVar, Callable, ParamSpec