perl5 icon indicating copy to clipboard operation
perl5 copied to clipboard

Improved diagnostic: "Can't return outside a subroutine" at compile time

Open epa opened this issue 1 year ago • 2 comments

Description The return keyword cannot be used outside a subroutine. It will give an error at run time. But it should be straightforward to check at compile time too. That would shorten the edit-test cycle a bit.

Steps to Reproduce

% perl -cE return
-e syntax OK
% perl -E return
Can't return outside a subroutine at -e line 1.

Expected behavior I would have liked the error to be given for the -c command line too, that is, caught at compile time.

Perl configuration

This is perl 5, version 26, subversion 3 (v5.26.3) built for x86_64-linux-thread-multi
(with 58 registered patches, see perl -V for more detail)
% rpm -q perl
perl-5.26.3-422.el8.x86_64

epa avatar Feb 19 '24 15:02 epa

This turns out to be not so trivial. Consider:

# foo.pl
return 42;

Obviously an error, right?

$ perl foo.pl
Can't return outside a subroutine at foo.pl line 2.

But:

$ perl -wE 'say do "./foo.pl"'
42

In other words, you can use return at file scope if that file is loaded with do (or return or use).

Similarly, take this module:

# Foo.pm
package Foo;
# ...
return 1;

Loads just fine using perl -Mlib=. -e 'use Foo'.

Now, if you want to check the syntax of this module, you can do:

$ perl -c Foo.pm 
Foo.pm syntax OK

But with your proposed change, this would turn into a syntax error. In other words, this change would break backwards compatibility.

mauke avatar Feb 19 '24 19:02 mauke

Thanks. I wasn't aware of return at file scope in modules because I have always ended them with just 1; rather than return 1;.

But I think it might be more than that: not just file scope but also inner scopes in a module can return.

package Foo;
if (1) { return 1 }

That works ok with perl -I. -MFoo -E0.

So perhaps the best that can be done is to change the error message. It's not that you can't return outside a subroutine. You can return only from a subroutine or from a library loaded with do or require or use.

Just possibly, I would want the compile time check if you return outside a subroutine and you're in package main; that would help my particular workflow of fairly short scripts; but it might be too specialized to be worth bothering.

epa avatar Feb 19 '24 19:02 epa