In the following example, the debugger hits a breakpoint that is set in the aVariable = ... line, which is in an if-statement whose condition is False and which should therefore not be executed. When I run the example with coverage (under PyCharm 2023.1), that line turns green. The print statement is not executed, which matches the expectation.
The assignment does not actually happen. It somehow just hits the line without really executing it.
Minimal reproducible example:
match 1:
case 1:
if False:
print('this should not be executed')
aVariable = 'somehow, we can hit a breakpoint here'
The same happens, if the last statement in the unreachable code is a pass. If I replace it with e.g. a print() statement, then everything behaves as expected.
If we extend the example a little bit, that behavior is reproducible for an unreachable else block, too:
match 1:
case 1:
if True:
pass
else:
anotherVariable = 'somehow, we can hit a breakpoint here, too'
Your environment
python --version
Python 3.11.3
lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.2 LTS
Release: 22.04
Codename: jammy
I initially encountered that behavior in a 3.10 version. Due to the fact that I thought, I could fix it with an upgrade to 3.11, I don't know the exact minor version of 3.10.
I double-checked this with the first online Python debugger that I could find and it behaves the same way.
Yeah, this is a bug, and should be fixed in 3.11. From a first glance, this should be as simple as saving and restoring the current location when entering/exiting case bodies in the compiler.
There are two places where VISIT_SEQ(c, stmt, m->body); is called in the 3.11 version of compile.c. I think that the fix should be as simple as calling UNSET_LOC(c); after each, to keep the last line number from leaking into the following control-flow.
This will also need one or more regression tests for the cases shown here. Thankfully, we already have good scaffolding for that in test.test_patma.TestTracing.
Even though the bug is only in 3.11, I'd like to see the tests forward-ported to 3.12 after.
I reproduced this in IDLE's debugger. Either 'Go' or 'Step, Step, Step' skips over line 4 to line 5, but a subsequent Go/Step does not execute line 5. Change line 5 to a print and is is skipped as expected. IDLE Debugger uses a subclass of bdb, so the bug is not in pdb.
changed the title [-]Match-case can hit a breakpoint in unreachable code and coverage turns green for that line[/-][+]Incorrect line numbers following `case` blocks[/+]on Apr 28, 2023
Activity
gaogaotiantian commented on Apr 28, 2023
Confirmed that this happens with pdb on 3.11 too. Not reproducible in main, bytecode is different.
3.11:
RETURN_VALUE was set at the last line(5) of the case block, so even though it's unreachable, it was hit.
3.12(main):
RETURN_CONST is at line 3, which is correct.
Not 100% sure if this is a bug that we want to fix in 3.11? 3.10 is already closed for bug fix right? We need expertise from the compiler side.
brandtbucher commented on Apr 28, 2023
Yeah, this is a bug, and should be fixed in 3.11. From a first glance, this should be as simple as saving and restoring the current location when entering/exiting case bodies in the compiler.
Any takers? Otherwise, I can pick it up.
brandtbucher commented on Apr 28, 2023
There are two places where VISIT_SEQ(c, stmt, m->body); is called in the 3.11 version of compile.c. I think that the fix should be as simple as calling UNSET_LOC(c); after each, to keep the last line number from leaking into the following control-flow.
brandtbucher commented on Apr 28, 2023
This will also need one or more regression tests for the cases shown here. Thankfully, we already have good scaffolding for that in test.test_patma.TestTracing.
Even though the bug is only in 3.11, I'd like to see the tests forward-ported to 3.12 after.
terryjreedy commented on Apr 28, 2023
I reproduced this in IDLE's debugger. Either 'Go' or 'Step, Step, Step' skips over line 4 to line 5, but a subsequent Go/Step does not execute line 5. Change line 5 to a print and is is skipped as expected. IDLE Debugger uses a subclass of bdb, so the bug is not in pdb.
brandtbucher commented on Apr 28, 2023
Yep, this is a compiler bug (3.12 cleaned up how we handle locations to avoid issues like this, which is why it's silently fixed there).
Rename 2023-04-28-18-57-13.gh-issue-pythongh-103971.Q3U9lv.rst to 202…
marvinweitzel commented on Apr 28, 2023
I just wanted to say how much I appreciate your responses and your extremely fast investigation of this issue.
Thanks a lot for taking this seriously!
Add unreachable line test per pythongh-103971
[3.11] GH-103971: Fix incorrect locations for code following case blocks
GH-103971: Forward-port test from GH-103980 (GH-103984)