develooper Front page | perl.perl5.porters | Postings from October 2011

[perl #101640] Stringify overload called too soon?

From:
Ben Morrow
Date:
October 20, 2011 03:21
Subject:
[perl #101640] Stringify overload called too soon?
Message ID:
rt-3.6.HEAD-31297-1318969358-1555.101640-75-0@perl.org
# New Ticket Created by  Ben Morrow 
# Please include the string:  [perl #101640]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=101640 >



This is a bug report for perl from ben@morrow.me.uk,
generated with the help of perlbug 1.39 running under perl 5.15.3.


-----------------------------------------------------------------
[Please describe your issue here]

If I have a class with both stringify and concat overloading, where
concat returns a new object, like this:

    package DeferConcat;

    use overload q/""/ => "force", q/./ => "concat";

    sub new     { bless [$_[1]] }
    sub force   { join "", @{$_[0]} }
    sub concat  { bless [@{$_[0]}, $_[1]] }

then interpolating one of these objects into a string and assigning it
to a lexical stringifies it all the way out to a plain string, rather
than returning the object from concat:

    my $o = DeferConcat->new("foo");
    my $x;              # $x needs to be already declared
    $x = "A $o B";      # $x is now *not* an object

This may not seem surprising, but in every other case perl just calls
concat overloading without stringifying, which for what I'm trying to do
is more useful. In particular, all of these give you an object:

    my $x = "A $o B";       # assign with LVINTRO
    $x = "A $o";            # interpolation with only two pieces
    $x = "" . "A $o B";     # random extra concatenation
    our $y;     $y = "A $o B";
    my $h;      $h{x} = "A $o B";

and indeed ref("A $o B") shows the bare expression is an object.

If this is a bug, then it comes from this bit of op.c (l9826 in blead)

    case OP_CONCAT:
        if (o->op_next && o->op_next->op_type == OP_STRINGIFY) {
            if (o->op_next->op_private & OPpTARGET_MY) {
                if (o->op_flags & OPf_STACKED) /* chained concats */
                    break; /* ignore_optimization */
                else {
                    /* steal the OP_STRINGIFY's targ */

where that 'break' causes the stringify not to get optimized away. I'm
not sure what the best way to fix it would be: the least intrusive would
be to give OP_STRINGIFY a private flag saying 'don't stringify at all,
just assign to your TARG', but it seems a bit odd to leave a stringify
op that doesn't actually stringify anything.

Ben

[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=core
    severity=low
---
Site configuration information for perl 5.15.3:

Configured by mauzo at Tue Oct 18 18:35:52 BST 2011.

Summary of my perl5 (revision 5 version 15 subversion 3) configuration:
  Commit id: 05f861a2cb5b8f36d571c879ab8b15dd52a612f7
  Platform:
    osname=freebsd, osvers=8.2-release-p2, archname=amd64-freebsd
    uname='freebsd anubis.morrow.me.uk 8.2-release-p2 freebsd 8.2-release-p2 #7: thu jun 9 14:58:42 bst 2011 mauzo@anubis:usrobjusrsrcsysanubis amd64 '
    config_args='-des -Dusedevel -Dprefix=/opt/blead -Uinstallusrbinperl'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include',
    optimize='-O',
    cppflags='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.2.1 20070719  [FreeBSD]', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags ='-Wl,-E  -fstack-protector -L/usr/local/lib'
    libpth=/usr/lib /usr/local/lib
    libs=-lgdbm -lm -lcrypt -lutil -lc
    perllibs=-lm -lcrypt -lutil -lc
    libc=, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' '
    cccdlflags='-DPIC -fPIC', lddlflags='-shared  -L/usr/local/lib -fstack-protector'

Locally applied patches:
    

---
@INC for perl 5.15.3:
    /opt/blead/lib/perl5/site_perl/5.15.3/amd64-freebsd
    /opt/blead/lib/perl5/site_perl/5.15.3
    /opt/blead/lib/perl5/5.15.3/amd64-freebsd
    /opt/blead/lib/perl5/5.15.3
    .

---
Environment for perl 5.15.3:
    HOME=/home/mauzo
    LANG (unset)
    LANGUAGE (unset)
    LC_ALL=en_GB.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/opt/blead/bin:/usr/local/libexec/ccache:/opt/tex/bin/amd64-freebsd:/usr/local/libexec/ccache:/opt/tex/bin/amd64-freebsd:/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/home/mauzo/bin
    PERLDOC_PAGER=vlm
    PERL_BADLANG (unset)
    SHELL=/usr/local/bin/mksh




nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About