Subject: | [PATCH] Fix to work with proxy constants |
As of perl 5.10 (or 5.8.9, maybe?) ‘use constant’ will put a simple reference to the constant in the stash, if there is no typeglob there already, to save memory. This ‘proxy’ of a typeglob will be upgraded to a full typeglob-with-CODE-thingy when appropriate.
Since NEXT.pm looks directly at the stash, it falls afoul of this optimisation and produces a ‘Not a GLOB reference’ error. It also conflicts with the subref-in-stash optimisation introduced in perl 5.22.
I am in the process of fixing perl bug #129916 (the subref-in-stash optimisation happens only in the main package), by extended it to happen in all packages, which was kind of the point to begin with. It causes NEXT.pm to fail its tests, so I will need to apply this patch to bleadperl soonish.
I am hoping that a new CPAN release can be made in the mean time, so that I do not have to patch bleadperl’s cpan/ directory directly.
Subject: | open_dmsDiwYc.txt |
diff -rup NEXT-0.67-cwUCVv-orig/lib/NEXT.pm NEXT-0.67-cwUCVv/lib/NEXT.pm
--- NEXT-0.67-cwUCVv-orig/lib/NEXT.pm 2016-07-30 02:41:57.000000000 -0700
+++ NEXT-0.67-cwUCVv/lib/NEXT.pm 2017-09-10 13:49:26.000000000 -0700
@@ -64,17 +64,19 @@ sub NEXT::ELSEWHERE::buildAUTOLOAD
last if shift @forebears eq $caller_class
}
no strict 'refs';
+ # Use *{"..."} when first accessing the CODE slot, to make sure
+ # any typeglob stub is upgraded to a full typeglob.
@{$NEXT::NEXT{$key,$wanted_method}} =
map {
my $stash = \%{"${_}::"};
- ($stash->{$caller_method} && (*{$stash->{$caller_method}}{CODE}))
+ ($stash->{$caller_method} && (*{"${_}::$caller_method"}{CODE}))
? *{$stash->{$caller_method}}{CODE}
: () } @forebears
unless $wanted_method eq 'AUTOLOAD';
@{$NEXT::NEXT{$key,$wanted_method}} =
map {
my $stash = \%{"${_}::"};
- ($stash->{AUTOLOAD} && (*{$stash->{AUTOLOAD}}{CODE}))
+ ($stash->{AUTOLOAD} && (*{"${_}::AUTOLOAD"}{CODE}))
? "${_}::AUTOLOAD"
: () } @forebears
unless @{$NEXT::NEXT{$key,$wanted_method}||[]};
diff -rup NEXT-0.67-cwUCVv-orig/t/next.t NEXT-0.67-cwUCVv/t/next.t
--- NEXT-0.67-cwUCVv-orig/t/next.t 2016-07-20 15:06:25.000000000 -0700
+++ NEXT-0.67-cwUCVv/t/next.t 2017-09-10 13:50:09.000000000 -0700
@@ -1,4 +1,4 @@
-BEGIN { print "1..26\n"; }
+BEGIN { print "1..27\n"; }
use NEXT;
@@ -16,13 +16,13 @@ sub B::AUTOLOAD { return ( 9, $_[0]->NEX
sub B::DESTROY { $_[0]->NEXT::DESTROY() }
package C;
-sub C::DESTROY { print "ok 24\n"; $_[0]->NEXT::DESTROY() }
+sub C::DESTROY { print "ok 25\n"; $_[0]->NEXT::DESTROY() }
package D;
@D::ISA = qw( B C E );
sub D::method { return ( 2, $_[0]->NEXT::method() ) }
sub D::AUTOLOAD { return ( 8, $_[0]->NEXT::AUTOLOAD() ) }
-sub D::DESTROY { print "ok 23\n"; $_[0]->NEXT::DESTROY() }
+sub D::DESTROY { print "ok 24\n"; $_[0]->NEXT::DESTROY() }
sub D::oops { $_[0]->NEXT::method() }
sub D::secondary { return ( 17, 18, map { $_+10 } $_[0]->NEXT::secondary() ) }
@@ -31,12 +31,12 @@ package E;
sub E::method { return ( 4, $_[0]->NEXT::method(), $_[0]->NEXT::method() ) }
sub E::AUTOLOAD { return ( 10, $_[0]->NEXT::AUTOLOAD() )
if $AUTOLOAD =~ /.*(missing_method|secondary)/ }
-sub E::DESTROY { print "ok 25\n"; $_[0]->NEXT::DESTROY() }
+sub E::DESTROY { print "ok 26\n"; $_[0]->NEXT::DESTROY() }
package F;
sub F::method { return ( 5 ) }
sub F::AUTOLOAD { return ( 11 ) if $AUTOLOAD =~ /.*(missing_method|secondary)/ }
-sub F::DESTROY { print "ok 26\n" }
+sub F::DESTROY { print "ok 27\n" }
package G;
sub G::method { return ( 6 ) }
@@ -104,4 +104,15 @@ eval {
};
print "ok 22\n";
-# CAN REDISPATCH DESTRUCTORS (ok 23..26)
+# TEST WITH CONSTANTS (23)
+
+package Hay;
+@ISA = 'Bee';
+sub foo { return shift->NEXT::foo }
+package Bee;
+use constant foo => 3;
+package main;
+print "not " unless Hay->foo eq '3';
+print "ok 23\n";
+
+# CAN REDISPATCH DESTRUCTORS (ok 24..27)