bpo-42246: Make sure that line number is correct after a return, as required by PEP 626 by markshannon · Pull Request #23495 · python/cpython

This PR ensures that f_lineno can be correctly computed after a return, by ensuring that all compiler generated return instructions
have a line number.

Any block that has no line numbers and has only one predecessor can inherit the line number from its predecessor.
Any block ending in a return has no successors, and thus can be safely duplicated.

By duplicating all blocks that end in a return, but have no line number, those blocks will have only one predecessor and thus can inherit its predecessor's line number, meaning that all implicit returns now have a line number.

For example,

currently compiles to:

  2           0 LOAD_FAST                0 (cond)
              2 POP_JUMP_IF_FALSE        8

  3           4 LOAD_GLOBAL              0 (a)
              6 POP_TOP
None    >>    8 LOAD_CONST               0 (None)
             10 RETURN_VALUE

with this PR it compiles to:

  2           0 LOAD_FAST                0 (cond)
              2 POP_JUMP_IF_FALSE       12

  3           4 LOAD_GLOBAL              0 (a)
              6 POP_TOP
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE

  2     >>   12 LOAD_CONST               0 (None)
             14 RETURN_VALUE

which is equivalent, but produces the correct line number when not cond.

https://bugs.python.org/issue42246