kikuchiyo has asked for the wisdom of the Perl Monks concerning the following question:

I've come across a strange case while refactoring some code at $work. This is a minimal example:

#!/usr/bin/perl use strict; use warnings; use List::Util qw/any/; sub foo { ###my $undeclared_variable = "Printing inside foo()\n"; print $undeclared_variable; } sub bar { my $params = {something => 'whatever'}; if (any { $params->{something} eq $_ } qw(some options or whatever +)) { print "Printing inside bar()\n"; } } foo(); bar();

This program is of course broken, $undeclared_variable is, true to its name, undeclared. However, when ran with perl 5.36.1, I get the following error messages:

Global symbol "$undeclared_variable" requires explicit package name (d +id you forget to declare "my $undeclared_variable"?) at perl_bad_erro +r_msg.pl line 9. Type of arg 1 to List::Util::any must be block or sub {} (not referenc +e constructor) at perl_bad_error_msg.pl line 14, near "qw(some option +s or whatever)) " Execution of perl_bad_error_msg.pl aborted due to compilation errors.

The first error message is valid, the second, however, is not. That line is fine, and indeed if you uncomment the variable declaration in foo(), the program runs without errors or warnings.

So where does the spurious error message come from? Does the presence of the first error push the interpreter in a state where the magic brace-guessing heuristics is broken?

Replies are listed 'Best First'.
Re: Where does the spurious error message come from?
by kikuchiyo (Hermit) on Aug 04, 2023 at 17:19 UTC

    Using the first service I've found when searching for "perl playground":

    https://perlbanjo.com/35ee31a0ab

    The spurious error message appeared in 5.20 and got fixed in 5.38.

      From the results at your link, 5.20 was the first version where List::Util contained any. It worked as expected in that version.

      It broke in 5.22, with the spurious error message

      The spurious error message appeared in 5.20 and got fixed in 5.38.

      I think the following excerpt from the 5.38.0 perldelta is relevant here:
      Syntax errors no longer produce "phantom error messages" Generally perl will continue parsing the source code even after encountering a compile error. In many cases this is helpful, for instance with misspelled variable names it is helpful to show as m +any examples of the error as possible. But in the case of syntax error +s continuing often produces bizarre error messages and may even caus +e segmentation faults during the compile process. In this release th +e compiler will halt at the first syntax error encountered. This mea +ns that any code expecting to see the specific error messages we used + to produce will be broken. The error that is emitted will be one of t +he diagnostics that used to be produced, but in some cases some messa +ges that used to be produced will no longer be displayed. See "Changes to Existing Diagnostics" for more details.
      Cheers,
      Rob
Re: Where does the spurious error message come from?
by kcott (Archbishop) on Aug 05, 2023 at 05:35 UTC

    G'day kikuchiyo,

    This is intended mainly as a confirmation that the problem was fixed in v5.38. I put "BEGIN { say $^V }" near the top of the script but otherwise left your code as is. I tried with v5.36.0 and v5.38.0 (I don't have v5.36.1 available).

    v5.36.0 Global symbol "$undeclared_variable" requires explicit package name .. +. Type of arg 1 to List::Util::any must be block or sub {} (not referenc +e constructor) ...
    v5.38.0 Global symbol "$undeclared_variable" requires explicit package name .. +.

    After uncommenting the my declaration:

    v5.36.0 Printing inside foo() Printing inside bar()
    v5.38.0 Printing inside foo() Printing inside bar()

    — Ken

      Less confusing error messages? What i strange concept!

      Truth be told, i love it but i never expected that i would ever see it happen.

      Sadly though, my idea of a contains() function for arrays was refused by the core team, so array checking is still ugly and error-prone. Guess i have to be content with ONE major improvement per release. I mean, i have Array::Contains, but that only runs at a fraction of the speed of a native solution...

      PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP

        How does it compare speed-wise with List::Util::any? I've always found that fast enough for my needs but maybe I'm just not very demanding.


        🦛

Re: Where does the spurious error message come from?
by LanX (Saint) on Aug 04, 2023 at 13:58 UTC
    Some additional info:

    > where the magic brace-guessing heuristics is broken?

    From List::More

    > any { BLOCK } @list;

    so any() has a prototype, so no "magic guessing" here, a {...} must be seen as a block.

    I can only guess your compile time error of an undeclared var aborts before properly importing any() with prototype.

    I think the problem might be even deeper.

    Cheers Rolf
    (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
    Wikisyntax for the Monastery

      If you switch the order of the functions in the code, the spurious error message goes away.

      By the way, I'd be interested to know how other versions of perl behave - IIRC there were some changes in 5.38 to error handling with the intent to show more readable error messages.

        A compiler that proceeds after recognising an error reminds me of the time when I had to program in PL/I. That beast was designed for those circumstances where you drop a box full of punched cards at the data centre's desk and get the compiler's result the next day. A missing semicolon would have cost you one full day unless the compiler were forgiving enough and guessed you intention. Some of the most serious programming errors, like assigning incompatible types, e.g. pointer to character, resulted in an inconspicuous warning "data conversion done by subroutine call".

        Greetings,
        -jo

        $gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$
        > you switch the order of the functions in the code, the spurious error message goes away.

        That's an indication that my direction of thinking was right.

        Only monks versed with the parser phases will be able to tell better

        But I see you just posted that it was fixed in 5.38, so maybe not worth further digging. :)

        Cheers Rolf
        (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
        Wikisyntax for the Monastery