develooper Front page | perl.perl5.porters | Postings from May 2019

[perl #134072] sub prototypes not tracking refalias \&foo = \&bar

Thread Next
From:
Tony Cook via RT
Date:
May 1, 2019 06:20
Subject:
[perl #134072] sub prototypes not tracking refalias \&foo = \&bar
Message ID:
rt-4.0.24-12721-1556691605-731.134072-15-0@perl.org
On Tue, 30 Apr 2019 16:50:20 -0700, jim.avera@gmail.com wrote:
> Not sure whether this is intended behavior, but just in case it's
> not...
> 
> The refalias
>   \&foo = \&bar
> is documented as "foo() now means bar()", but it doesn't entirely:
> 
> In subsequently-compiled code, the compiler still wants calls
> to foo() to match the old foo's prototype, not the prototype of bar.
> 
> 
> #! /usr/bin/perl
> use strict; use warnings; use v5.22.0;
> 
> use feature 'refaliasing';
> no warnings 'experimental::refaliasing';
> 
> sub foo($$$$) { }
> sub bar($) { }
> 
> BEGIN{ \&foo = \&bar; }
> 
> foo(1);  # Gets "Not enough arguments for main::foo"

It's worse than that:

./perl -Ilib -Mfeature=refaliasing -e 'sub foo { print "foo\n" } sub bar { print "bar\n" } \&foo = \&bar; $n = "foo"; &$n'
Aliasing via reference is experimental at -e line 1.
foo

It seems to be caused by the optimization of storing coderefs as GVs - pp_refassign is expecting a GV on the left for your sample code, but gets the CVref instead and so nothing happens:

    switch (left ? SvTYPE(left) : 0) {
    case 0:
    {
	SV * const old = PAD_SV(ARGTARG);
	PAD_SETSV(ARGTARG, SvREFCNT_inc_NN(SvRV(sv)));
	SvREFCNT_dec(old);
	if ((PL_op->op_private & (OPpLVAL_INTRO|OPpPAD_STATE))
		== OPpLVAL_INTRO)
	    SAVECLEARSV(PAD_SVl(ARGTARG));
	break;
    }
    case SVt_PVGV:
	if (PL_op->op_private & OPpLVAL_INTRO) {
	    S_localise_gv_slot(aTHX_ (GV *)left, type);
	}
	gv_setref(left, sv);
	SvSETMAGIC(left);
	break;
    case SVt_PVAV:
        assert(key);
	if (UNLIKELY(PL_op->op_private & OPpLVAL_INTRO)) {
	    S_localise_aelem_lval(aTHX_ (AV *)left, key,
					SvCANEXISTDELETE(left));
	}
	av_store((AV *)left, SvIV(key), SvREFCNT_inc_simple_NN(SvRV(sv)));
	break;
    case SVt_PVHV:
        if (UNLIKELY(PL_op->op_private & OPpLVAL_INTRO)) {
            assert(key);
	    S_localise_helem_lval(aTHX_ (HV *)left, key,
					SvCANEXISTDELETE(left));
        }
	(void)hv_store_ent((HV *)left, key, SvREFCNT_inc_simple_NN(SvRV(sv)), 0);
    }

Tony

---
via perlbug:  queue: perl5 status: new
https://rt.perl.org/Ticket/Display.html?id=134072

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About