Skip Menu |
Report information
Id: 132793
Status: resolved
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: zefram [at] fysh.org
Cc:
AdminCc:

Operating System: (no value)
PatchStatus: (no value)
Severity: medium
Type: core
Perl Version: 5.27.8
Fixed In: 5.27.9



Subject: $a.="$b" doesn't stringify $b
Date: Wed, 31 Jan 2018 13:16:59 +0000
From: zefram [...] fysh.org
To: perlbug [...] perl.org
CC: zefram [...] fysh.org
Download (untitled) / with headers
text/plain 4.2k
This is a bug report for perl from zefram@fysh.org, generated with the help of perlbug 1.41 running under perl 5.27.8. ----------------------------------------------------------------- [Please describe your issue here] Another multiconcat bug: $ perl5.27.5 -lwe 'package Lhs { use overload ".=" => sub { warn ref(\$_[1]); "foo"; }; } package Rhs { use overload "\"\"" => sub { warn "stringified"; "bar" }; } my $a = bless({}, "Lhs"); my $b = bless({}, "Rhs"); $a .= "$b"' stringified at -e line 1. SCALAR at -e line 1. $ perl5.27.8 -lwe 'package Lhs { use overload ".=" => sub { warn ref(\$_[1]); "foo"; }; } package Rhs { use overload "\"\"" => sub { warn "stringified"; "bar" }; } my $a = bless({}, "Lhs"); my $b = bless({}, "Rhs"); $a .= "$b"' REF at -e line 1. Passing the rhs reference through to the lhs overload method would be correct if the expression were '$a .= $b', and indeed both perl versions do pass it through in that case. But explicit stringification must be honoured. Found this while testing around [perl #132783]. [Please do not change anything below this line] ----------------------------------------------------------------- --- Flags: category=core severity=medium --- Site configuration information for perl 5.27.8: Configured by zefram at Sat Jan 20 03:46:58 GMT 2018. Summary of my perl5 (revision 5 version 27 subversion 8) configuration: Platform: osname=linux osvers=3.16.0-4-amd64 archname=x86_64-linux-thread-multi uname='linux barba.rous.org 3.16.0-4-amd64 #1 smp debian 3.16.43-2+deb8u2 (2017-06-26) x86_64 gnulinux ' config_args='-des -Dprefix=/home/zefram/usr/perl/perl_install/perl-5.27.8-i64-f52 -Duselargefiles -Dusethreads -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dusedevel -Uversiononly -Ui_db' hint=recommended useposix=true d_sigaction=define useithreads=define usemultiplicity=define use64bitint=define use64bitall=define uselongdouble=undef usemymalloc=n default_inc_excludes_dot=define bincompat5005=undef Compiler: cc='cc' ccflags ='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2' optimize='-O2' cppflags='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include' ccversion='' gccversion='4.9.2' gccosandvers='' intsize=4 longsize=8 ptrsize=8 doublesize=8 byteorder=12345678 doublekind=3 d_longlong=define longlongsize=8 d_longdbl=define longdblsize=16 longdblkind=3 ivtype='long' ivsize=8 nvtype='double' nvsize=8 Off_t='off_t' lseeksize=8 alignbytes=8 prototype=define Linker and Libraries: ld='cc' ldflags =' -fstack-protector-strong -L/usr/local/lib' libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib libs=-lpthread -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc libc=libc-2.19.so so=so useshrplib=true libperl=libperl.so gnulibc_version='2.19' Dynamic Linking: dlsrc=dl_dlopen.xs dlext=so d_dlsymun=undef ccdlflags='-Wl,-E -Wl,-rpath,/home/zefram/usr/perl/perl_install/perl-5.27.8-i64-f52/lib/5.27.8/x86_64-linux-thread-multi/CORE' cccdlflags='-fPIC' lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector-strong' --- @INC for perl 5.27.8: /home/zefram/usr/perl/perl_install/perl-5.27.8-i64-f52/lib/site_perl/5.27.8/x86_64-linux-thread-multi /home/zefram/usr/perl/perl_install/perl-5.27.8-i64-f52/lib/site_perl/5.27.8 /home/zefram/usr/perl/perl_install/perl-5.27.8-i64-f52/lib/5.27.8/x86_64-linux-thread-multi /home/zefram/usr/perl/perl_install/perl-5.27.8-i64-f52/lib/5.27.8 --- Environment for perl 5.27.8: HOME=/home/zefram LANG (unset) LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/home/zefram/usr/perl/perl_install/perl-5.27.8-i64-f52/bin:/home/zefram/usr/perl/util:/home/zefram/pub/x86_64-unknown-linux-gnu/bin:/home/zefram/pub/common/bin:/usr/bin:/bin:/usr/local/bin:/usr/games PERL_BADLANG (unset) SHELL=/usr/bin/zsh
Date: Tue, 20 Feb 2018 09:23:59 +0000
From: Dave Mitchell <davem [...] iabyn.com>
Subject: Re: [perl #132793] $a.="$b" doesn't stringify $b
To: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 2.8k
On Wed, Jan 31, 2018 at 05:17:18AM -0800, Zefram wrote: Show quoted text
> Another multiconcat bug: > > $ perl5.27.5 -lwe 'package Lhs { use overload ".=" => sub { warn ref(\$_[1]); "foo"; }; } package Rhs { use overload "\"\"" => sub { warn "stringified"; "bar" }; } my $a = bless({}, "Lhs"); my $b = bless({}, "Rhs"); $a .= "$b"' > stringified at -e line 1. > SCALAR at -e line 1. > $ perl5.27.8 -lwe 'package Lhs { use overload ".=" => sub { warn ref(\$_[1]); "foo"; }; } package Rhs { use overload "\"\"" => sub { warn "stringified"; "bar" }; } my $a = bless({}, "Lhs"); my $b = bless({}, "Rhs"); $a .= "$b"' > REF at -e line 1. > > Passing the rhs reference through to the lhs overload method would be > correct if the expression were '$a .= $b', and indeed both perl versions > do pass it through in that case. But explicit stringification must > be honoured. > > Found this while testing around [perl #132783].
Now fixed with the following commit. Note that it merely restores the existing buggy and inconsistent 5.26.0 and earlier behaviour. I'll look into whether to rationalise such behaviour post 5.28.0 release. commit 55b62dee2d8dffa7b36b3b613ee4727fbefdb9e3 Author: David Mitchell <davem@iabyn.com> AuthorDate: Mon Feb 19 11:59:03 2018 +0000 Commit: David Mitchell <davem@iabyn.com> CommitDate: Mon Feb 19 22:06:49 2018 +0000 pp_multiconcat: correctly honour stringify RT #132793, RT #132801 In something like $x .= "$overloaded", the $overloaded stringify method wasn't being called. However, it turns that the existing (pre-multiconcat) behaviour is also buggy and inconsistent. That behaviour has been restored as-is. At some future time, these bugs might be addressed. Here are some comments from the new tests added to overload.t: Since 5.000, any OP_STRINGIFY immediately following an OP_CONCAT is optimised away, on the assumption that since concat will always return a valid string anyway, it doesn't need stringifying. So in "$x", the stringify is needed, but on "$x$y" it isn't. This assumption is flawed once overloading has been introduced, since concat might return an overloaded object which still needs stringifying. However, this flawed behaviour is apparently needed by at least one module, and is tested for in opbasic/concat.t: see RT #124160. There is also a wart with the OPpTARGET_MY optimisation: specifically, in $lex = "...", if $lex is a lexical var, then a chain of 2 or more concats *doesn't* optimise away OP_STRINGIFY: $lex = "$x"; # stringifies $lex = "$x$y"; # doesn't stringify $lex = "$x$y$z..."; # stringifies -- More than any other time in history, mankind faces a crossroads. One path leads to despair and utter hopelessness. The other, to total extinction. Let us pray we have the wisdom to choose correctly. -- Woody Allen


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org