Skip to content

Return with a bareword compiles under strict #21716

Description

@bbrtj

Description

return sum map { ... } @list seems to compile OK under strict without the import of List::Util::sum and returns a filehandle and a mapped list.

Steps to Reproduce
This program shows the behavior:

use warnings;
use strict;

use Data::Dumper;
# use List::Util qw{ sum };

sub xx { return sum map { $_ + 1 } 1 .. 5 }
print Dumper(xx);

The actual error occurs only after you remove return. Removing map causes it to report a warning, but it still runs.

Expected behavior

I expected to get an error about invalid bareword under strict mode, same as without return.

Perl configuration
Behavior is consistent on both perl 5.10.1 and 5.38.2.

Activity

  1. tonycoz commented on Dec 18, 2023

    @tonycoz
    Contributor

    This has to do with the way list ops are parsed. One of the possible productions for a listop in the grammar is:

    listop	:	LSTOP indirob listexpr
    

    where LSTOP is the op (OP_RETURN, OP_PRINT etc), indirob is a file handle, and listexpr is the list, this production is used to parse code like:

    print HANDLE LIST;
    

    It also parses other code like:

    atan2 HANDLE y, x
    

    which parses, but is then rejected in the op's check function (which is Perl_ck_fun, used by many other ops).

    I'll look at a fix.

  2. added a commit that references this issue on Dec 18, 2023
    83308cc
  3. added 2 commits that reference this issue on Dec 18, 2023
    12ea353
    daf305d
  4. added 2 commits that reference this issue on Dec 19, 2023
    5394776
    f41b73e
  5. rwp0 commented on Dec 20, 2023

    @rwp0
    Contributor

    I expected to get an error about invalid bareword under strict mode, same as without return.

    (F) While certain operators allow you to specify a filehandle or an "indirect object" before the argument list, return isn't one of them.

    Why not?

    Worth mentioning that it's also because return could be implicit (producing different results).

  6. tonycoz commented on Dec 20, 2023

    @tonycoz
    Contributor

    Why not?

    Because it's documented not to do so:

        return EXPR
        return  Returns from a subroutine, "eval", "do FILE", "sort" block or
                regex eval block (but not a "grep", "map", or "do BLOCK" block)
                with the value given in EXPR. Evaluation of EXPR may be in list,
    ...
    

    The other operators that take an indirect object are output operators like print that treat the object as a file handle, what do you expect return to do with an indirect object?

    Worth mentioning that it's also because `return` could be implicit (producing different results).
    

    I'm not sure what you mean here, at first I thought you might mean returning by running off the end of a function, but that's unrelated to the return operator.

  7. rwp0 commented on Dec 20, 2023

    @rwp0
    Contributor

    Why not?

    Because it's documented not to do so:

        return EXPR
        return  Returns from a subroutine, "eval", "do FILE", "sort" block or
                regex eval block (but not a "grep", "map", or "do BLOCK" block)
                with the value given in EXPR. Evaluation of EXPR may be in list,
    ...
    

    The other operators that take an indirect object are output operators like print that treat the object as a file handle, what do you expect return to do with an indirect object?

    Worth mentioning that it's also because `return` could be implicit (producing different results).
    

    I'm not sure what you mean here, at first I thought you might mean returning by running off the end of a function, but that's unrelated to the return operator.

    Ah no, I meant if we omit return at the end of a function there won't be issues. This was confusing the OP (poster), apparently. I thought it'd be good to mention that in the message (a fact that sets return apart from the other OPs).

    Thank you very much for the commits 👍🏻

  8. bbrtj commented on Dec 21, 2023

    @bbrtj
    ContributorAuthor

    Ah no, I meant if we omit return at the end of a function there won't be issues. This was confusing the OP (poster), apparently. I thought it'd be good to mention that in the message (a fact that sets return apart from the other OPs).

    I'm not confused, I understand implicit return may not work the same as explicit. I just did not think return should mask errors like that. But I'd rather not to depend on implicit behavior in case of returning.

    Thanks for the fix, Tony.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions