Skip to content

Commit b60d4c0

Browse files
authored
gh-118090: Improve error message for empty type param brackets (GH-118091)
1 parent 0485922 commit b60d4c0

File tree

4 files changed

+1016
-800
lines changed

4 files changed

+1016
-800
lines changed

Grammar/python.gram

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,11 @@ function_def[stmt_ty]:
269269

270270
function_def_raw[stmt_ty]:
271271
| invalid_def_raw
272-
| 'def' n=NAME t=[type_params] &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
272+
| 'def' n=NAME t=[type_params] '(' params=[params] ')' a=['->' z=expression { z }] ':' tc=[func_type_comment] b=block {
273273
_PyAST_FunctionDef(n->v.Name.id,
274274
(params) ? params : CHECK(arguments_ty, _PyPegen_empty_arguments(p)),
275275
b, NULL, a, NEW_TYPE_COMMENT(p, tc), t, EXTRA) }
276-
| 'async' 'def' n=NAME t=[type_params] &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
276+
| 'async' 'def' n=NAME t=[type_params] '(' params=[params] ')' a=['->' z=expression { z }] ':' tc=[func_type_comment] b=block {
277277
CHECK_VERSION(
278278
stmt_ty,
279279
5,
@@ -641,7 +641,9 @@ type_alias[stmt_ty]:
641641
# Type parameter declaration
642642
# --------------------------
643643

644-
type_params[asdl_type_param_seq*]: '[' t=type_param_seq ']' {
644+
type_params[asdl_type_param_seq*]:
645+
| invalid_type_params
646+
| '[' t=type_param_seq ']' {
645647
CHECK_VERSION(asdl_type_param_seq *, 12, "Type parameter lists are", t) }
646648

647649
type_param_seq[asdl_type_param_seq*]: a[asdl_type_param_seq*]=','.type_param+ [','] { a }
@@ -1392,6 +1394,7 @@ invalid_for_stmt:
13921394
invalid_def_raw:
13931395
| ['async'] a='def' NAME [type_params] '(' [params] ')' ['->' expression] ':' NEWLINE !INDENT {
13941396
RAISE_INDENTATION_ERROR("expected an indented block after function definition on line %d", a->lineno) }
1397+
| ['async'] 'def' NAME [type_params] &&'(' [params] ')' ['->' expression] &&':' [func_type_comment] block
13951398
invalid_class_def_raw:
13961399
| 'class' NAME [type_params] ['(' [arguments] ')'] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
13971400
| a='class' NAME [type_params] ['(' [arguments] ')'] ':' NEWLINE !INDENT {
@@ -1435,3 +1438,9 @@ invalid_arithmetic:
14351438
| sum ('+'|'-'|'*'|'/'|'%'|'//'|'@') a='not' b=inversion { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "'not' after an operator must be parenthesized") }
14361439
invalid_factor:
14371440
| ('+' | '-' | '~') a='not' b=factor { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "'not' after an operator must be parenthesized") }
1441+
1442+
invalid_type_params:
1443+
| '[' token=']' {
1444+
RAISE_SYNTAX_ERROR_STARTING_FROM(
1445+
token,
1446+
"Type parameter list cannot be empty")}

Lib/test/test_syntax.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,22 @@
12131213
Traceback (most recent call last):
12141214
SyntaxError: expected '('
12151215
1216+
>>> def f -> int:
1217+
Traceback (most recent call last):
1218+
SyntaxError: expected '('
1219+
1220+
>>> async def f -> int: # type: int
1221+
Traceback (most recent call last):
1222+
SyntaxError: expected '('
1223+
1224+
>>> async def f[T]:
1225+
Traceback (most recent call last):
1226+
SyntaxError: expected '('
1227+
1228+
>>> def f[T] -> str:
1229+
Traceback (most recent call last):
1230+
SyntaxError: expected '('
1231+
12161232
Parenthesized arguments in function definitions
12171233
12181234
>>> def f(x, (y, z), w):
@@ -2027,6 +2043,31 @@ def f(x: *b)
20272043
20282044
Invalid expressions in type scopes:
20292045
2046+
>>> type A[] = int
2047+
Traceback (most recent call last):
2048+
...
2049+
SyntaxError: Type parameter list cannot be empty
2050+
2051+
>>> class A[]: ...
2052+
Traceback (most recent call last):
2053+
...
2054+
SyntaxError: Type parameter list cannot be empty
2055+
2056+
>>> def some[](): ...
2057+
Traceback (most recent call last):
2058+
...
2059+
SyntaxError: Type parameter list cannot be empty
2060+
2061+
>>> def some[]()
2062+
Traceback (most recent call last):
2063+
...
2064+
SyntaxError: Type parameter list cannot be empty
2065+
2066+
>>> async def some[]: # type: int
2067+
Traceback (most recent call last):
2068+
...
2069+
SyntaxError: Type parameter list cannot be empty
2070+
20302071
>>> type A[T: (x:=3)] = int
20312072
Traceback (most recent call last):
20322073
...
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve :exc:`SyntaxError` message for empty type param brackets.

0 commit comments

Comments
 (0)