-
-
Notifications
You must be signed in to change notification settings - Fork 31.2k
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
gh-129093: Fix f-string debug text sometimes getting cut off when expression contains !
#129159
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a correct analysis.
Thanks a lot @tomasr8 for dedicating the time to chase the original cause
I have made some spelunking and I have chased this code to the original implementation in commit 1ef61cf. The code was protecting against a condition that is not true anymore and unfortunately never got removed |
Thanks @tomasr8 for the PR, and @pablogsal for merging it 🌮🎉.. I'm working now to backport this PR to: 3.12. |
Thanks @tomasr8 for the PR, and @pablogsal for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13. |
Sorry, @tomasr8 and @pablogsal, I could not cleanly backport this to
|
…en expression contains `!` (pythonGH-129159) (cherry picked from commit 767cf70) Co-authored-by: Tomas R. <[email protected]>
GH-129163 is a backport of this pull request to the 3.13 branch. |
|
@freakboy3742: This iOS failure has happened twice in the last 24 hours on each of the main and 3.13 branches, but with successful builds in between. |
Yeah is certainly unrelated to this PR |
Yeah - this specific failure is a weird race condition that I thought would be fairly rare, but I've now seen it a couple of times. Logged as #129200. |
Here's what I think is happening (though I may be wrong, the lexer code and especially the f-string code is really complex):
For an f-string replacement field such as
{1!=2=}
we end up in this branch of the parser:cpython/Grammar/python.gram
Lines 916 to 918 in 29caec6
The original source (i.e.
debug_expr
) is stored on therbrace
'stoken->metadata
:cpython/Parser/lexer/lexer.c
Line 171 in 29caec6
which is how the
_PyPegen_formatted_value
function injects it into the AST (asdebug_text
):cpython/Parser/action_helpers.c
Lines 1492 to 1493 in 29caec6
The
token->metadata
itself gets the debug text fromtok_mode->last_expr_buffer
andtok_mode->last_expr_end
.cpython/Parser/lexer/lexer.c
Lines 159 to 163 in 29caec6
If we go back to the example
{1!=2=}
, to parse thefstring_replacement_field
rule, the parser first tries to parse theannotated_rhs
which consumes1
at first since it's a valid expression. It then skipsdebug_expr='='?
and starts parsing the conversion specifier which matches the following!
. Now that it hit!
, it setstok_mode->last_expr_end
in_PyLexer_update_fstring_expr
:cpython/Parser/lexer/lexer.c
Lines 212 to 218 in 29caec6
The problem is that now the parser needs to backtrack. The second time it parses the full
1!=2
asannotated_rhs
but becausetok_mode->last_expr_end
is guarded withif(tok_mode->last_expr_end == -1){}
it never gets updated which is what is causing this issue.Simply removing that if check seems to work, but I'm not 100% sure this is the best way to fix it. It'd be great if a parser expert could check this :)