Subject: | dualvar doesn't capture numeric value |
Date: | Mon, 24 Jul 2017 10:11:34 +0100 |
To: | bug-Scalar-List-Utils [...] rt.cpan.org |
From: | Zefram <zefram [...] fysh.org> |
$ perl5.26.0 -MConfig -lwe 'print "$Config{ivsize} $Config{nvsize}"'
8 8
$ perl5.26.0 -MScalar::Util=dualvar -lwe '$a = "4611686018427387915"; print $a - (1<<62); print dualvar($a, "foo") - (1<<62)'
11
0
In this and many related cases, dualvar() fails to accurately copy the
numeric value of its numeric input into its output. In this case, it's
assuming that because $a has a PV its numeric value must arise only
through NV semantics. That used to be the case in Perl 5.6 outside
the scope of "use integer", but hasn't been true of Perl's default
arithmetic from 5.8 onwards, and even in 5.6 wasn't true if "use integer"
got involved.
Beware of funny cases that change behaviour between Perl versions,
like this:
$ perl5.12.0 -lwe '$a = "-0"; printf "%+.f%+.f\n", -$a, - - - -$a'
+0-0
$ perl5.16.0 -lwe '$a = "-0"; printf "%+.f%+.f\n", -$a, - - - -$a'
-0+0
$ perl5.26.0 -lwe '$a = "-0"; printf "%+.f%+.f\n", -$a, - - - -$a'
+0+0
The big changes in numeric semantics occur at Perl versions 5.7.1,
5.13.6, and 5.17.1. From Perl 5.13.6 onwards, "-0" and a couple of
others are actually so weird that their numeric behaviour cannot be fully
captured by a set of IV and NV fields and IOK and NOK flags. dualvar()
obviously cannot completely copy these numeric values across losslessly.
But the same strings produce normal numeric values on other Perl versions,
and dualvar() needs to handle them properly on those versions.
-zefram