Skip to content

Note (yyl_leftcurly) & restore (newATTRSUB_x) line numbers for anon subs#24396

Open
richardleach wants to merge 2 commits into
Perl:bleadfrom
richardleach:mid_statement_sub_copline
Open

Note (yyl_leftcurly) & restore (newATTRSUB_x) line numbers for anon subs#24396
richardleach wants to merge 2 commits into
Perl:bleadfrom
richardleach:mid_statement_sub_copline

Conversation

@richardleach
Copy link
Copy Markdown
Contributor

Declaring an anonymous subroutine in the middle of a statement is likely to result in an inaccurate line number being stored in the COP preceding the statement. This is because line number information is discarded during parsing and creation of the anonymous subroutine.

This commit attempts to store and restore a more accurate line number for the COP. This will improve the accuracy of line numbers emitted by diagnostic messages and caller(). Tests containing hardcoded line numbers may require updating as a result of this commit.

This (previously) TODO test from caller.t shows the difference:

    sub tagCall {
        my ($package, $file, $line) = caller;
        print "$line\n";
      }

      tagCall    # Line number 6 correctly reported before & after
      "abc";

      tagCall    # Line number 9 correctly reported with this commit
      sub {};    # Line number 10 incorrectly reported previously

Changes in line numbering could also affect where breaking on a function occurs in the perl debugger. This can be seen in the included change to perl5db.t, where breaking on entry to problem() now occurs at the start of the subroutine, rather than after the anonymous subroutine declaration:

sub problem {
    $SIG{__DIE__} = sub {  # Breaking on problem() now lands here
        die "<b problem> will set a break point here.\n";
    };    # Breaking on problem() used to land here

Closes #4125


  • This set of changes requires a perldelta entry. I'll hopefully have 2-3 line number fixup PRs ready for 5.45.1 and will write a combined perldelta entry prior to that release.

Declaring an anonymous subroutine in the middle of a statement is likely
to result in an inaccurate line number being stored in the COP preceding
the statement. This is because line number information is discarded
during parsing and creation of the anonymous subroutine.

This commit attempts to store and restore a more accurate line number
for the COP. This will improve the accuracy of line numbers emitted by
diagnostic messages and `caller()`. **_Tests containing hardcoded line
numbers may require updating as a result of this commit._**

This (previously) TODO test from _caller.t_ shows the difference:

```
    sub tagCall {
        my ($package, $file, $line) = caller;
        print "$line\n";
      }

      tagCall    # Line number 6 correctly reported before & after
      "abc";

      tagCall    # Line number 9 correctly reported with this commit
      sub {};    # Line number 10 incorrectly reported previously
```

Changes in line numbering could also affect where breaking on a function
occurs in the perl debugger. This can be seen in the included change to
_perl5db.t_, where breaking on entry to `problem()` now occurs at the
start of the subroutine, rather than after the anonymous subroutine
declaration:

```
sub problem {
    $SIG{__DIE__} = sub {  # Breaking on problem() now lands here
        die "<b problem> will set a break point here.\n";
    };    # Breaking on problem() used to land here
```
@richardleach richardleach added the defer-next-dev This PR should not be merged yet, but await the next development cycle label Apr 28, 2026
@richardleach richardleach requested a review from tonycoz April 28, 2026 12:21
@richardleach
Copy link
Copy Markdown
Contributor Author

  1. This change breaks some /Legacy/ tests in Test::Simple. Presumably we'd want some form of compatible PR merged upstream prior to merging this PR into blead. I'll work on those if we're happy with the changed line numbers.
  2. I've never really used the debugger, so am unsure whether the change in behaviour is fine or would be problematic. (It appears to be an improvement...) @tonycoz - please could you advise?
  3. I'm wary of this PR triggering BBC tickets and will endeavour to test some high-on-the-river modules ahead of 5.45.1.

@tonycoz
Copy link
Copy Markdown
Contributor

tonycoz commented Apr 28, 2026

2. I've never really used the debugger, so am unsure whether the change in behaviour is fine or would be problematic. (It appears to be an improvement...) @tonycoz - please could you advise?

From what I understand it's breaking on the same dbstate, it's just the line number is from the beginning of the statement rather than the end.

I certainly prefer that.

I could it briefly confusing people who are used to the old behaviour, but I think it's preferable (especially since the anonsub can be much longer.

One issue I could see (for the debugger) is there will be different conflicts between which dbstate is saved in the IV of the ${"_<$filename"}[$line_number] elements, but that's mostly just going to be different, rather than necessarily worse.

A C debugger would likely set the breakpoint on every piece of generated code for that line, but we only store one address for each line, and compatibility makes that hard(er) to change (maybe store the extras in magic?).

3. I'm wary of this PR triggering BBC tickets and will endeavour to test some high-on-the-river modules ahead of 5.45.1.

I expect it will generate a painful amount of BBC.

@richardleach
Copy link
Copy Markdown
Contributor Author

richardleach commented May 1, 2026

Note to future self, something like this can be used in test files to determine the behaviour at run time and then adjust expectations to match:

# Detect the line numbering behaviour of this version of perl
our $use_block_end;
BEGIN {
    sub X { my (undef, undef, $line) = caller;
                $use_block_end++ if ($line != shift); }
    X __LINE__, # $use_block_end = 0
    sub { }     # $use_block_end = 1
};

@richardleach
Copy link
Copy Markdown
Contributor Author

While working through Test::Simple's test failures, it became apparent that this PR was incomplete. Pushed an additional commit so that the copline being tracked isn't wiped out by a newSTATEOP call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

defer-next-dev This PR should not be merged yet, but await the next development cycle do not merge Don't merge this PR, at least for now

Projects

None yet

Development

Successfully merging this pull request may close these issues.

caller() reports $line numbers inconsistently

2 participants