7

Am fighting some legacy perl looking like the following:

sub UNIVERSAL::has_sub_class {
    my ($package,$class) = @_;
    my $all = all_packages();
    print "$package - $class", "\n";
    print "$package::$class", "\n";
    return exists $all->{"$package::$class"};
}

On two different systems, two different PERL installations / versions, this code behaves differently, i.e. the "$package::$class" construct is properly resolved to the correct package name on one system, but not on the other.

The following different print outputs can be seen when running has_sub_class on the two different systems:

# print output on system 1 (perl v5.8.6):
webmars::parameter=HASH(0xee93d0) - webmars::parameter::date
webmars::parameter::date

# print output on system 2 (perl v5.18.1):
webmars::parameter=HASH(0x251c500) - webmars::parameter::date
webmars::parameter=HASH(0x251c500)::webmars::parameter::date

Has there been any string interpolation changes in between perl v5.8.6 and perl v5.18.1 that you know might cause this behaviour ? Or should I look somewhere else ? I've really tried google-ing around and reading through the perl change notes, but could not find anything of interest.

With my limited knowledge of perl, I've tried getting the smallest piece of code that could reproduce the problem I am having. I have come up with the following which I hope is relevant:

# system 1 (perl v5.8.6):
$ perl -e 'my %x=(),$x=bless(\%x),$y='bar';print "$x::$y\n";'
bar

# system 2 (perl v5.18.1):
$ perl -e 'my %x=(),$x=bless(\%x),$y='bar';print "$x::$y\n";'
main=HASH(0xec0ce0)::bar

The outputs are different ! Any ideas ?

2
  • perl -Mstrict -we 'my %x=(),$x=bless(\%x),$y='bar';print "$x::$y\n";' Commented May 12, 2015 at 15:20
  • 2
    Could quite easily be a bug fixed in the intervening 6 years between the releases :). But well done for such a concise MCVE! Commented May 12, 2015 at 15:37

2 Answers 2

4

Shorter demonstration:

($x::, $x) = (1,2);  print "$x::$x"

$ perl5.16.3 -e '($x::, $x) = (1,2);  print "$x::$x"'
12

$ perl5.18.1 -e '($x::, $x) = (1,2);  print "$x::$x"'
2::2

Getting warmer.

$ perl5.16.3 -MO=Concise =e 'print "$x::$x"'
8  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
7     <@> print vK ->8
3        <0> pushmark s ->4
-        <1> ex-stringify sK/1 ->7
-           <0> ex-pushmark s ->4
6           <2> concat[t3] sK/2 ->7
-              <1> ex-rv2sv sK/1 ->5
4                 <#> gvsv[*x::] s ->5          <-     $x::
-              <1> ex-rv2sv sK/1 ->6
5                 <#> gvsv[*x] s ->6            <-     $x
-e syntax OK

$ perl5.18.1 -MO=Concise -e 'print "$x::$x"'
a  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
9     <@> print vK ->a
3        <0> pushmark s ->4
-        <1> ex-stringify sK/1 ->9
-           <0> ex-pushmark s ->4
8           <2> concat[t4] sKS/2 ->9
6              <2> concat[t2] sK/2 ->7
-                 <1> ex-rv2sv sK/1 ->5
4                    <#> gvsv[*x] s ->5         <-     $x
5                 <$> const[PV "::"] s ->6      <-     "::"
-              <1> ex-rv2sv sK/1 ->8
7                 <#> gvsv[*x] s ->8            <-     $x
-e syntax OK

TL;DR. v5.16 parses "$x::$x" as $x:: . $x. v5.18 as $x . "::" . $x. I don't see any obvious reference to this change in the delta docs, but I'll keep looking.

Sign up to request clarification or add additional context in comments.

2 Comments

Indeed, it looks like there was a bug in the code which was being silenced due tot "$x::$x" parsing as $x:: . $x, i.e. "$package::$class" would look for $package:: instead of $package and end up replacing it with `` in the string since it's undefined.
Rewrite that as ${package}::$class to get it work in any version of perl.
3

So, my very quick test confirms the issue - using

perl -Mstrict -we 'my %x=(),$x=bless(\%x),$y="bar";print "$x::$y\n";'

(With your version, I get a bareword warning for 'bar').

The error I get in 5.8.8 is "use of uninitialized value in concatenation".

The difference seems to be that when I run with perl -MO=Deparse I get:

my ( %x ) = ();
my $x = bless ( \%x );
my $y = 'bar';
print "$x::$y\n";

If I run on 5.20.2 though, I get:

my ( %x ) = ();
my $x = bless ( \%x );
my $y = 'bar';
print "${x}::$y\n";

So yes, there has been a change in how the same code is parsed. But I'm not entirely sure how that helps you, apart from perhaps enlightening you as to what's going on?

1 Comment

It does help me a lot to understand where the problem is coming from, if it's the perl interpreter, or issues in the code. And in this case, it's a combination of both.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.