Open leonerd opened 7 months ago
The explanation for this is that, unlike most "weird kinds of values", vstrings are magicalised PVs themselves, rather than object refs. The value is directly an SV containing a PV string, which additionally has the PERL_MAGIC_vstring
magic applied to.
The Perl_sv_setsv()
function makes a special-case to handle copying that magic around the place, which is why my $vstr = v...
actually works. However, in the implementation of overloaded stringification there is no place in which to copy that value around. The tmpstr
that overloaded stringifcation obtains in Perl_sv_2pv_flags()
contains that magic annotation but it is not possible to copy it "out of" that function and into the caller, because the caller invoked some variant of the SvPV
macro in order to directly obtain the char * / STRLEN
pair of the underlying string buffer. This forgot that it was a vstring.
Isn't that the expected behavior?
$ perl -wE 'use Scalar::Util qw(isvstring); my $vstr = v48.49.50; say isvstring("$vstr") ? "yes" : "no"'
no
The result of stringifying a v-string is a plain string. The result of stringifying an object (overloaded or not) should also be a plain string.
We may want to consider removing vstring magic. I don't think it is necessary anymore for version.pm to work correctly. And if version.pm does still need it, we should look at fixing that.
I thought the problem was without magic you can't reliably distinguish between v50.46.49
and 2.1
. Has that changed?
The original purpose of vstring magic was to maintain the exact initial formatting of vstrings, including underscores. Because version.pm wanted to treat underscores as a special case of a .
.
If an object class provides overloaded stringification, and you attempt to return a vstring as the result of that stringify, perl will forget that the vstring is a vstring and retain only its "plain" PV representation:
A vstring should look like:
However, sending the result via overloaded stringify forgets this fact: