summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJelle Zijlstra <jelle.zijlstra@gmail.com>2023-10-18 05:26:34 (GMT)
committerGitHub <noreply@github.com>2023-10-18 05:26:34 (GMT)
commit2bca5f43af8fc1c7643fb7769d04a25fbd5f0d98 (patch)
tree930ede65a8998242c5b5f6ed477b1084a7bd9190
parent8134811089f1907ea56085c6a7de9ce0afbc56c8 (diff)
downloadcpython-2bca5f43af8fc1c7643fb7769d04a25fbd5f0d98.zip
cpython-2bca5f43af8fc1c7643fb7769d04a25fbd5f0d98.tar.gz
cpython-2bca5f43af8fc1c7643fb7769d04a25fbd5f0d98.tar.bz2
[3.12] gh-110938: Fix error messages for indented blocks with functio… (#110990)
[3.12] gh-110938: Fix error messages for indented blocks with functions and classes with generic type parameters (GH-110973) (cherry picked from commit 24e4ec7766fd471deb5b7e5087f0e7dba8576cfb) Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>
-rw-r--r--Grammar/python.gram6
-rw-r--r--Lib/test/test_syntax.py10
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-10-17-11-03-45.gh-issue-110938.X3sbMb.rst2
-rw-r--r--Parser/parser.c50
4 files changed, 46 insertions, 22 deletions
diff --git a/Grammar/python.gram b/Grammar/python.gram
index c442db2..a4fd3f2 100644
--- a/Grammar/python.gram
+++ b/Grammar/python.gram
@@ -1369,11 +1369,11 @@ invalid_for_stmt:
| [ASYNC] a='for' star_targets 'in' star_expressions ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after 'for' statement on line %d", a->lineno) }
invalid_def_raw:
- | [ASYNC] a='def' NAME '(' [params] ')' ['->' expression] ':' NEWLINE !INDENT {
+ | [ASYNC] a='def' NAME [type_params] '(' [params] ')' ['->' expression] ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after function definition on line %d", a->lineno) }
invalid_class_def_raw:
- | 'class' NAME ['(' [arguments] ')'] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
- | a='class' NAME ['(' [arguments] ')'] ':' NEWLINE !INDENT {
+ | 'class' NAME [type_params] ['(' [arguments] ')'] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
+ | a='class' NAME [type_params] ['(' [arguments] ')'] ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after class definition on line %d", a->lineno) }
invalid_double_starred_kvpairs:
diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py
index 52fc357..f5cf966 100644
--- a/Lib/test/test_syntax.py
+++ b/Lib/test/test_syntax.py
@@ -1446,11 +1446,21 @@ Specialized indentation errors:
Traceback (most recent call last):
IndentationError: expected an indented block after function definition on line 1
+ >>> def foo[T](x, /, y, *, z=2):
+ ... pass
+ Traceback (most recent call last):
+ IndentationError: expected an indented block after function definition on line 1
+
>>> class Blech(A):
... pass
Traceback (most recent call last):
IndentationError: expected an indented block after class definition on line 1
+ >>> class Blech[T](A):
+ ... pass
+ Traceback (most recent call last):
+ IndentationError: expected an indented block after class definition on line 1
+
>>> match something:
... pass
Traceback (most recent call last):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-10-17-11-03-45.gh-issue-110938.X3sbMb.rst b/Misc/NEWS.d/next/Core and Builtins/2023-10-17-11-03-45.gh-issue-110938.X3sbMb.rst
new file mode 100644
index 0000000..a2f9319
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-10-17-11-03-45.gh-issue-110938.X3sbMb.rst
@@ -0,0 +1,2 @@
+Fix error messages for indented blocks with functions and classes with
+generic type parameters. Patch by Pablo Galindo
diff --git a/Parser/parser.c b/Parser/parser.c
index 42201c4..25b4ead 100644
--- a/Parser/parser.c
+++ b/Parser/parser.c
@@ -24069,7 +24069,7 @@ invalid_for_stmt_rule(Parser *p)
}
// invalid_def_raw:
-// | ASYNC? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT
+// | ASYNC? 'def' NAME type_params? '(' params? ')' ['->' expression] ':' NEWLINE !INDENT
static void *
invalid_def_raw_rule(Parser *p)
{
@@ -24082,12 +24082,12 @@ invalid_def_raw_rule(Parser *p)
}
void * _res = NULL;
int _mark = p->mark;
- { // ASYNC? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT
+ { // ASYNC? 'def' NAME type_params? '(' params? ')' ['->' expression] ':' NEWLINE !INDENT
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> invalid_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT"));
+ D(fprintf(stderr, "%*c> invalid_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'def' NAME type_params? '(' params? ')' ['->' expression] ':' NEWLINE !INDENT"));
Token * _literal;
Token * _literal_1;
Token * _literal_2;
@@ -24097,6 +24097,8 @@ invalid_def_raw_rule(Parser *p)
UNUSED(_opt_var_1); // Silence compiler warnings
void *_opt_var_2;
UNUSED(_opt_var_2); // Silence compiler warnings
+ void *_opt_var_3;
+ UNUSED(_opt_var_3); // Silence compiler warnings
Token * a;
expr_ty name_var;
Token * newline_var;
@@ -24107,13 +24109,15 @@ invalid_def_raw_rule(Parser *p)
&&
(name_var = _PyPegen_name_token(p)) // NAME
&&
+ (_opt_var_1 = type_params_rule(p), !p->error_indicator) // type_params?
+ &&
(_literal = _PyPegen_expect_token(p, 7)) // token='('
&&
- (_opt_var_1 = params_rule(p), !p->error_indicator) // params?
+ (_opt_var_2 = params_rule(p), !p->error_indicator) // params?
&&
(_literal_1 = _PyPegen_expect_token(p, 8)) // token=')'
&&
- (_opt_var_2 = _tmp_226_rule(p), !p->error_indicator) // ['->' expression]
+ (_opt_var_3 = _tmp_226_rule(p), !p->error_indicator) // ['->' expression]
&&
(_literal_2 = _PyPegen_expect_token(p, 11)) // token=':'
&&
@@ -24122,7 +24126,7 @@ invalid_def_raw_rule(Parser *p)
_PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, INDENT) // token=INDENT
)
{
- D(fprintf(stderr, "%*c+ invalid_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT"));
+ D(fprintf(stderr, "%*c+ invalid_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'def' NAME type_params? '(' params? ')' ['->' expression] ':' NEWLINE !INDENT"));
_res = RAISE_INDENTATION_ERROR ( "expected an indented block after function definition on line %d" , a -> lineno );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -24133,7 +24137,7 @@ invalid_def_raw_rule(Parser *p)
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s invalid_def_raw[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC? 'def' NAME type_params? '(' params? ')' ['->' expression] ':' NEWLINE !INDENT"));
}
_res = NULL;
done:
@@ -24142,8 +24146,8 @@ invalid_def_raw_rule(Parser *p)
}
// invalid_class_def_raw:
-// | 'class' NAME ['(' arguments? ')'] NEWLINE
-// | 'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT
+// | 'class' NAME type_params? ['(' arguments? ')'] NEWLINE
+// | 'class' NAME type_params? ['(' arguments? ')'] ':' NEWLINE !INDENT
static void *
invalid_class_def_raw_rule(Parser *p)
{
@@ -24156,15 +24160,17 @@ invalid_class_def_raw_rule(Parser *p)
}
void * _res = NULL;
int _mark = p->mark;
- { // 'class' NAME ['(' arguments? ')'] NEWLINE
+ { // 'class' NAME type_params? ['(' arguments? ')'] NEWLINE
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> invalid_class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] NEWLINE"));
+ D(fprintf(stderr, "%*c> invalid_class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] NEWLINE"));
Token * _keyword;
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
+ void *_opt_var_1;
+ UNUSED(_opt_var_1); // Silence compiler warnings
expr_ty name_var;
Token * newline_var;
if (
@@ -24172,12 +24178,14 @@ invalid_class_def_raw_rule(Parser *p)
&&
(name_var = _PyPegen_name_token(p)) // NAME
&&
- (_opt_var = _tmp_227_rule(p), !p->error_indicator) // ['(' arguments? ')']
+ (_opt_var = type_params_rule(p), !p->error_indicator) // type_params?
+ &&
+ (_opt_var_1 = _tmp_227_rule(p), !p->error_indicator) // ['(' arguments? ')']
&&
(newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE'
)
{
- D(fprintf(stderr, "%*c+ invalid_class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] NEWLINE"));
+ D(fprintf(stderr, "%*c+ invalid_class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] NEWLINE"));
_res = RAISE_SYNTAX_ERROR ( "expected ':'" );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -24188,17 +24196,19 @@ invalid_class_def_raw_rule(Parser *p)
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s invalid_class_def_raw[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'class' NAME ['(' arguments? ')'] NEWLINE"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] NEWLINE"));
}
- { // 'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT
+ { // 'class' NAME type_params? ['(' arguments? ')'] ':' NEWLINE !INDENT
if (p->error_indicator) {
p->level--;
return NULL;
}
- D(fprintf(stderr, "%*c> invalid_class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT"));
+ D(fprintf(stderr, "%*c> invalid_class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] ':' NEWLINE !INDENT"));
Token * _literal;
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
+ void *_opt_var_1;
+ UNUSED(_opt_var_1); // Silence compiler warnings
Token * a;
expr_ty name_var;
Token * newline_var;
@@ -24207,7 +24217,9 @@ invalid_class_def_raw_rule(Parser *p)
&&
(name_var = _PyPegen_name_token(p)) // NAME
&&
- (_opt_var = _tmp_228_rule(p), !p->error_indicator) // ['(' arguments? ')']
+ (_opt_var = type_params_rule(p), !p->error_indicator) // type_params?
+ &&
+ (_opt_var_1 = _tmp_228_rule(p), !p->error_indicator) // ['(' arguments? ')']
&&
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
&&
@@ -24216,7 +24228,7 @@ invalid_class_def_raw_rule(Parser *p)
_PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, INDENT) // token=INDENT
)
{
- D(fprintf(stderr, "%*c+ invalid_class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT"));
+ D(fprintf(stderr, "%*c+ invalid_class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] ':' NEWLINE !INDENT"));
_res = RAISE_INDENTATION_ERROR ( "expected an indented block after class definition on line %d" , a -> lineno );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -24227,7 +24239,7 @@ invalid_class_def_raw_rule(Parser *p)
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s invalid_class_def_raw[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] ':' NEWLINE !INDENT"));
}
_res = NULL;
done: