Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make PEP 695 constructs give a reasonable error message #16013

Merged
merged 2 commits into from
Sep 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 31 additions & 0 deletions mypy/fastparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ def ast3_parse(
NamedExpr = ast3.NamedExpr
Constant = ast3.Constant

if sys.version_info >= (3, 12):
ast_TypeAlias = ast3.TypeAlias
else:
ast_TypeAlias = Any

if sys.version_info >= (3, 10):
Match = ast3.Match
MatchValue = ast3.MatchValue
Expand Down Expand Up @@ -936,6 +941,14 @@ def do_func_def(
arg_types = [AnyType(TypeOfAny.from_error)] * len(args)
return_type = AnyType(TypeOfAny.from_error)
else:
if sys.version_info >= (3, 12) and n.type_params:
self.fail(
ErrorMessage("PEP 695 generics are not yet supported", code=codes.VALID_TYPE),
n.type_params[0].lineno,
n.type_params[0].col_offset,
blocker=False,
)

arg_types = [a.type_annotation for a in args]
return_type = TypeConverter(
self.errors, line=n.returns.lineno if n.returns else lineno
Expand Down Expand Up @@ -1110,6 +1123,14 @@ def visit_ClassDef(self, n: ast3.ClassDef) -> ClassDef:
self.class_and_function_stack.append("C")
keywords = [(kw.arg, self.visit(kw.value)) for kw in n.keywords if kw.arg]

if sys.version_info >= (3, 12) and n.type_params:
self.fail(
ErrorMessage("PEP 695 generics are not yet supported", code=codes.VALID_TYPE),
n.type_params[0].lineno,
n.type_params[0].col_offset,
blocker=False,
)

cdef = ClassDef(
n.name,
self.as_required_block(n.body),
Expand Down Expand Up @@ -1717,6 +1738,16 @@ def visit_MatchOr(self, n: MatchOr) -> OrPattern:
node = OrPattern([self.visit(pattern) for pattern in n.patterns])
return self.set_line(node, n)

def visit_TypeAlias(self, n: ast_TypeAlias) -> AssignmentStmt:
self.fail(
ErrorMessage("PEP 695 type aliases are not yet supported", code=codes.VALID_TYPE),
n.lineno,
n.col_offset,
blocker=False,
)
node = AssignmentStmt([NameExpr(n.name.id)], self.visit(n.value))
return self.set_line(node, n)


class TypeConverter:
def __init__(
Expand Down
4 changes: 3 additions & 1 deletion mypy/test/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,9 @@ def num_skipped_suffix_lines(a1: list[str], a2: list[str]) -> int:


def testfile_pyversion(path: str) -> tuple[int, int]:
if path.endswith("python311.test"):
if path.endswith("python312.test"):
return 3, 12
elif path.endswith("python311.test"):
return 3, 11
elif path.endswith("python310.test"):
return 3, 10
Expand Down
2 changes: 2 additions & 0 deletions mypy/test/testcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
typecheck_files.remove("check-python310.test")
if sys.version_info < (3, 11):
typecheck_files.remove("check-python311.test")
if sys.version_info < (3, 12):
typecheck_files.remove("check-python312.test")

# Special tests for platforms with case-insensitive filesystems.
if sys.platform not in ("darwin", "win32"):
Expand Down
59 changes: 59 additions & 0 deletions test-data/unit/check-python312.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
[case test695TypeAlias]
type MyInt = int # E: PEP 695 type aliases are not yet supported

def f(x: MyInt) -> MyInt:
return reveal_type(x) # N: Revealed type is "builtins.int"

type MyList[T] = list[T] # E: PEP 695 type aliases are not yet supported \
# E: Name "T" is not defined

def g(x: MyList[int]) -> MyList[int]: # E: Variable "__main__.MyList" is not valid as a type \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
return reveal_type(x) # N: Revealed type is "MyList?[builtins.int]"

[case test695Class]
class MyGen[T]: # E: PEP 695 generics are not yet supported
def __init__(self, x: T) -> None: # E: Name "T" is not defined
self.x = x

def f(x: MyGen[int]): # E: "MyGen" expects no type arguments, but 1 given
reveal_type(x.x) # N: Revealed type is "Any"

[case test695Function]
def f[T](x: T) -> T: # E: PEP 695 generics are not yet supported \
# E: Name "T" is not defined
return reveal_type(x) # N: Revealed type is "Any"

reveal_type(f(1)) # N: Revealed type is "Any"

async def g[T](x: T) -> T: # E: PEP 695 generics are not yet supported \
# E: Name "T" is not defined
return reveal_type(x) # N: Revealed type is "Any"

reveal_type(g(1)) # E: Value of type "Coroutine[Any, Any, Any]" must be used \
# N: Are you missing an await? \
# N: Revealed type is "typing.Coroutine[Any, Any, Any]"

[case test695TypeVar]
from typing import Callable
type Alias1[T: int] = list[T] # E: PEP 695 type aliases are not yet supported
type Alias2[**P] = Callable[P, int] # E: PEP 695 type aliases are not yet supported \
# E: Value of type "int" is not indexable \
# E: Name "P" is not defined
type Alias3[*Ts] = tuple[*Ts] # E: PEP 695 type aliases are not yet supported \
# E: Type expected within [...] \
# E: The type "Type[Tuple[Any, ...]]" is not generic and not indexable \
# E: Name "Ts" is not defined

class Cls1[T: int]: ... # E: PEP 695 generics are not yet supported
class Cls2[**P]: ... # E: PEP 695 generics are not yet supported
class Cls3[*Ts]: ... # E: PEP 695 generics are not yet supported

def func1[T: int](x: T) -> T: ... # E: PEP 695 generics are not yet supported
def func2[**P](x: Callable[P, int]) -> Callable[P, str]: ... # E: PEP 695 generics are not yet supported \
# E: The first argument to Callable must be a list of types, parameter specification, or "..." \
# N: See https://mypy.readthedocs.io/en/stable/kinds_of_types.html#callable-types-and-lambdas \
# E: Name "P" is not defined
def func3[*Ts](x: tuple[*Ts]) -> tuple[int, *Ts]: ... # E: PEP 695 generics are not yet supported \
# E: Name "Ts" is not defined
[builtins fixtures/tuple.pyi]