diff options
author | Jelle Zijlstra <jelle.zijlstra@gmail.com> | 2023-10-18 05:26:34 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-18 05:26:34 (GMT) |
commit | 2bca5f43af8fc1c7643fb7769d04a25fbd5f0d98 (patch) | |
tree | 930ede65a8998242c5b5f6ed477b1084a7bd9190 | |
parent | 8134811089f1907ea56085c6a7de9ce0afbc56c8 (diff) | |
download | cpython-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.gram | 6 | ||||
-rw-r--r-- | Lib/test/test_syntax.py | 10 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2023-10-17-11-03-45.gh-issue-110938.X3sbMb.rst | 2 | ||||
-rw-r--r-- | Parser/parser.c | 50 |
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: |