Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tied hash key stringification weirdness #13666

Open
p5pRT opened this issue Mar 15, 2014 · 1 comment
Open

tied hash key stringification weirdness #13666

p5pRT opened this issue Mar 15, 2014 · 1 comment

Comments

@p5pRT
Copy link

p5pRT commented Mar 15, 2014

Migrated from rt.perl.org#121446 (status was 'new')

Searchable as RT121446$

@p5pRT
Copy link
Author

p5pRT commented Mar 15, 2014

From zefram@fysh.org

Created by zefram@fysh.org

In the tied hash system, the documentation isn't clear about whether
a hash key is intended to be strictly a string, as it is for ordinary
hashes, or whether it can be an arbitrary object that the tie class can
interpret in its own way. The interface to the methods such as FETCH
obviously could accommodate values other than strings.

What actually happens doesn't follow either of the possible coherent
systems. In fact, if a reference (say) is used as a hash key, what is
passed to the FETCH method is the reference itself, not a string derived
from it. So that looks as though the key is an unrestricted parameter
that can have significant structure. But before the key is passed
to FETCH, it is first stringified, and apparently the result of that
stringification is thrown away. So an object can only be used as a hash
key if it can be stringified, and if the FETCH method wants to use the key
purely as a string then it must stringify it a second time, potentially
by magic getting a different result from the first stringification.

Demo​:

$ perl -MDevel​::Peek -lwe 'package Foo { sub TIEHASH { bless({}, "Foo") } sub FETCH { Devel​::Peek​::Dump $_[1]; undef } } package Bar { sub new { bless({},"Bar") } use overload "\"\"" => sub { print "overload called"; }; } tie %a, "Foo"; $b = Bar->new; $_ = $a{$b}'
overload called
SV = IV(0x1f879a0) at 0x1f879b0
  REFCNT = 2
  FLAGS = (ROK)
  RV = 0x1f878c0
  SV = PVHV(0x1f70980) at 0x1f878c0
  REFCNT = 2
  FLAGS = (OBJECT,SHAREKEYS)
  STASH = 0x1f92a50 "Bar"
  ARRAY = 0x0
  KEYS = 0
  FILL = 0
  MAX = 7

If the "print" is changed to "die", so that the object can't be
stringified, the program dies before getting to FETCH.

The FIRSTKEY/NEXTKEY system consistently accepts non-string keys, and
doesn't stringify them. Overall, of the coherent options we're closer to
the system where keys can be of any type, governed only by the particular
tie class. I think we should move to using that system consistently,
by removing the extraneous stringifications that I've described.

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.19.9:

Configured by zefram at Thu Feb 20 19:48:37 GMT 2014.

Summary of my perl5 (revision 5 version 19 subversion 9) configuration:
   
  Platform:
    osname=linux, osvers=3.2.0-4-amd64, archname=x86_64-linux-thread-multi
    uname='linux barba.rous.org 3.2.0-4-amd64 #1 smp debian 3.2.46-1 x86_64 gnulinux '
    config_args='-des -Dprefix=/home/zefram/usr/perl/perl_install/perl-5.19.9-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, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.7.2', 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 =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/4.7/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=-lnsl -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=libc-2.17.so, so=so, useshrplib=true, libperl=libperl.so
    gnulibc_version='2.17'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/home/zefram/usr/perl/perl_install/perl-5.19.9-i64-f52/lib/5.19.9/x86_64-linux-thread-multi/CORE'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector'



@INC for perl 5.19.9:
    /home/zefram/usr/perl/perl_install/perl-5.19.9-i64-f52/lib/site_perl/5.19.9/x86_64-linux-thread-multi
    /home/zefram/usr/perl/perl_install/perl-5.19.9-i64-f52/lib/site_perl/5.19.9
    /home/zefram/usr/perl/perl_install/perl-5.19.9-i64-f52/lib/5.19.9/x86_64-linux-thread-multi
    /home/zefram/usr/perl/perl_install/perl-5.19.9-i64-f52/lib/5.19.9
    .


Environment for perl 5.19.9:
    HOME=/home/zefram
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/zefram/usr/perl/perl_install/perl-5.19.9-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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants