From c874eddad1ddb0d031fae1d369eee586af872079 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Fri, 25 Aug 2023 20:43:51 +0100 Subject: [PATCH] Use dedicated error; fix Parameters location --- mypy/typeanal.py | 26 ++++++++++++++++--- .../unit/check-parameter-specification.test | 10 +++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 7da1e0a99602..e29cca09be63 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -465,9 +465,23 @@ def pack_paramspec_args(self, an_args: Sequence[Type]) -> list[Type]: # I didn't find this in the PEP, but it sounds reasonable. return list(an_args) if any(isinstance(a, (Parameters, ParamSpecType)) for a in an_args): - # Nested parameter specifications are not allowed. + if len(an_args) > 1: + first_wrong = next( + arg for arg in an_args if isinstance(arg, (Parameters, ParamSpecType)) + ) + self.fail( + "Nested parameter specifications are not allowed", + first_wrong, + code=codes.VALID_TYPE, + ) + return [AnyType(TypeOfAny.from_error)] return list(an_args) - return [Parameters(an_args, [ARG_POS] * count, [None] * count)] + first = an_args[0] + return [ + Parameters( + an_args, [ARG_POS] * count, [None] * count, line=first.line, column=first.column + ) + ] def cannot_resolve_type(self, t: UnboundType) -> None: # TODO: Move error message generation to messages.py. We'd first @@ -508,7 +522,11 @@ def apply_concatenate_operator(self, t: UnboundType) -> Type: names: list[str | None] = [None] * len(args) pre = Parameters( - args + pre.arg_types, [ARG_POS] * len(args) + pre.arg_kinds, names + pre.arg_names + args + pre.arg_types, + [ARG_POS] * len(args) + pre.arg_kinds, + names + pre.arg_names, + line=t.line, + column=t.column, ) return ps.copy_modified(prefix=pre) if isinstance(ps, ParamSpecType) else pre @@ -918,7 +936,7 @@ def visit_type_list(self, t: TypeList) -> Type: if params: ts, kinds, names = params # bind these types - return Parameters(self.anal_array(ts), kinds, names) + return Parameters(self.anal_array(ts), kinds, names, line=t.line, column=t.column) else: return AnyType(TypeOfAny.from_error) else: diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index 7d92c0800313..257fb9241373 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -1754,3 +1754,13 @@ def dec(fn: Callable[P, T]) -> Alias[P, T]: ... # type: ignore f: Any dec(f) # No crash [builtins fixtures/paramspec.pyi] + +[case testParamSpecErrorNestedParams] +from typing import Generic +from typing_extensions import ParamSpec + +P = ParamSpec("P") +class C(Generic[P]): ... +c: C[int, [int, str], str] # E: Nested parameter specifications are not allowed +reveal_type(c) # N: Revealed type is "__main__.C[Any]" +[builtins fixtures/paramspec.pyi]