develooper Front page | perl.perl5.porters | Postings from April 2012

Re: [perl #24250] "return" required in some anonymous closures

Dave Mitchell
April 20, 2012 08:55
Re: [perl #24250] "return" required in some anonymous closures
Message ID:
On Fri, Apr 20, 2012 at 12:37:55PM +0100, Nicholas Clark wrote:
> now takes advantage of the "proxy constant subroutines"
> on all versions from 5.10.0 onwards. It no longer users the fragile
> "feature" under discussion here, that
>     *foo::bar = sub () { $baz; }

Well, having a quick look at, it may use the new method as its
primary route, buts there's still plenly of places where it uses the old
mechanism, even down to

    my $const = $] > 5.009002;
    *_CAN_PCS = sub () {$const};

[ just by-the-by, I don't understand why is written in such a
way as to be able to run under old perls; its not as if its a dual-life
CPAN distribution ]

I don't know enough about how the new method works to be abloe to say
whether it can be rewritten to avoid sub(){$x} completely, or whether
we need to add some sort of XS mechanism for the general case.

> So, do we want to remove the inlining of (inferred to be)-constant value
> closures? And only inline subroutines that trivially return true constants.
> And fix this 5.8.0 regression. What is relying on the regressed behaviour?
> In the general case, is it impossible to detect all scenarios where the
> variable within the closure can not later be modified?

It's effectively impossible, and its trivially easy to later modify the
For example under 5.8.0, where the refcnt < 2 test was done at compile
time, the 1st sub would see a refcnt of 1 and mark the sub as 'convert to
const when cloning at time', then compiling the second sub retractively
allows you to modify the var:

	my $x = ...;
	sub () {$x};      # at compile time, has refcnt==1, looks safe...
	sub bad { $x++ }; # ..but it isn't

After I changed it so that the refcnt < 2 test is done at runtime during
cloning, that can be defeated with

	my $x = ...;
	sub () {$x};     # at runtime, has refcnt==1, looks safe...
	$::global = \$x; # now has a refcnt of 2, so isn't safe

So, I think we should remove this 'feature'.
If anyone is using it as intended, then the worst they'll get is
a performance decrease, with a const sub downgraded to a real sub that
returns the expected value. Perhaps we could issue a warning, with
perldiag.pod explaining what to do if you really wanted a const sub, and
to stick a 'return' in to defeat the warning if you didn't want it.

Dave's first rule of Opera:
If something needs saying, say it: don't warble it. Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About