perl5
perl5 copied to clipboard
Builtin stringify - Undefined subroutine &main::stringify called
Description When using forward coderef to imported builtin current blead (sha: af9733f1e2) doesn't assign ref properly, though it does it when builtin is not used or when ref is evaluated after builtin.
Steps to Reproduce
my $coderef = \&stringify;
use builtin q (stringify);
CORE::say $coderef->({});
Hint: address of function changes:
my $coderef = \ &stringify;
use builtin q (stringify);
sub stringify ($) { q (foo) }
CORE::say q ([1] ), $coderef;
CORE::say q ([2] ), \ &stringify;
Result:
[1] CODE(0x5576ca60b648)
[2] CODE(0x5576ca639dc0)
Expected behavior When given coderef already exists in namespace import builtin so that it doesn't change symbol's refaddr.
Perl configuration
$ git log -1 --oneline
af9733f1e2 (HEAD -> blead, upstream/blead, upstream/HEAD) builtin.c: Remember to EXTEND() before using XSRETURN_{YES,NO}
$ ./perl -I lib -V
Summary of my perl5 (revision 5 version 39 subversion 8) configuration:
Commit id: af9733f1e2152339a4db682937e7c6c6ee95b5fb
Platform:
osname=linux
osvers=5.15.0-92-generic
archname=x86_64-linux
uname='linux happy-barney 5.15.0-92-generic #102-ubuntu smp wed jan 10 09:33:48 utc 2024 x86_64 x86_64 x86_64 gnulinux '
config_args='-des -Dusedevel -DDEBUGGING'
hint=previous
useposix=true
d_sigaction=define
useithreads=undef
usemultiplicity=undef
use64bitint=define
use64bitall=define
uselongdouble=undef
usemymalloc=n
default_inc_excludes_dot=define
Compiler:
cc='cc'
ccflags ='-fwrapv -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
optimize='-O2 -g'
cppflags='-fwrapv -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
ccversion=''
gccversion='11.4.0'
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/x86_64-linux-gnu /usr/lib /usr/lib64
libs=-lpthread -ldb -ldl -lm -lcrypt -lutil -lc
perllibs=-lpthread -ldl -lm -lcrypt -lutil -lc
libc=/lib/x86_64-linux-gnu/libc.so.6
so=so
useshrplib=false
libperl=libperl.a
gnulibc_version='2.35'
Dynamic Linking:
dlsrc=dl_dlopen.xs
dlext=so
d_dlsymun=undef
ccdlflags='-Wl,-E'
cccdlflags='-fPIC'
lddlflags='-shared -O2 -g -L/usr/local/lib -fstack-protector-strong'
Characteristics of this binary (from libperl):
Compile-time options:
DEBUGGING
HAS_LONG_DOUBLE
HAS_STRTOLD
HAS_TIMES
PERLIO_LAYERS
PERL_COPY_ON_WRITE
PERL_DONT_CREATE_GVSV
PERL_HASH_FUNC_SIPHASH13
PERL_HASH_USE_SBOX32
PERL_MALLOC_WRAP
PERL_OP_PARENT
PERL_PRESERVE_IVUV
PERL_USE_DEVEL
PERL_USE_SAFE_PUTENV
USE_64_BIT_ALL
USE_64_BIT_INT
USE_LARGE_FILES
USE_LOCALE
USE_LOCALE_COLLATE
USE_LOCALE_CTYPE
USE_LOCALE_NUMERIC
USE_LOCALE_TIME
USE_PERLIO
USE_PERL_ATOF
Built under linux
Compiled at Jan 27 2024 21:20:48
%ENV:
PERL5LIB="/home/brano/lib/perl5/:/home/brano/lib/perl5/:/home/brano/lib/perl5/"
PERLBREW_HOME="/home/brano/.perlbrew"
PERLBREW_PATH="/home/brano/.cache/perlbrew/bin"
PERLBREW_ROOT="/home/brano/.cache/perlbrew"
PERLBREW_SHELLRC_VERSION="0.86"
PERLBREW_VERSION="0.94"
@INC:
lib
/home/brano/lib/perl5/
/home/brano/lib/perl5/
/home/brano/lib/perl5/
/home/brano/.cache/perlbrew/perls/latest_blead/lib/site_perl/5.39.8/x86_64-linux
/home/brano/.cache/perlbrew/perls/latest_blead/lib/site_perl/5.39.8
/home/brano/.cache/perlbrew/perls/latest_blead/lib/5.39.8/x86_64-linux
/home/brano/.cache/perlbrew/perls/latest_blead/lib/5.39.8
I can confirm that when, in blead, I run the program in @happy-barney's 2nd code block above, I get the results he displayed in his 3rd code block. I can also confirm that when I built at 7c60f1f796a4c23bbfc43b25f2e159ffea14300b -- the commit whose message indicates that it was the place where builtin::stringify was implemented on Sep 8 2023 -- that I get similar results.
I don't know enough about builtin to comment further.
This isn't really a builtin thing, but a lexical subs thing. In fact, it's just a general lexical thing, with subs only being different because you are allowed to bind to them without declaring them even under strict.
use strict;
use warnings;
my $coderef = \&code;
my sub code { 1 }
print q(code:), "\n";
print q([1] ), $coderef, "\n";
print q([2] ), \&code, "\n";
no strict 'vars';
no warnings 'once';
my $scalarref = \$scalar;
my $scalar = 1;
print q(scalar:), "\n";
print q([1] ), $scalarref, "\n";
print q([2] ), \$scalar, "\n";
__END__
code:
[1] CODE(0x13f80ae10)
[2] CODE(0x13f824500)
scalar:
[1] SCALAR(0x13f865b80)
[2] SCALAR(0x13f824578)
Perhaps builtin::import could check if the sub already has a definition in the calling package/pad.
As far as it looks like that root caused directly by builtin::import I'd suggest to experiment with source code finding combinations where behaviour is "very different from expected" or inconsistent between different versions and different entity types (eg variables vs functions) and fix (aka well define) it.
This seems to me to be acting as expected.
It behaves how I expect.
It would be good if we could warn here, but I'm not sure how practical it is.
Furthermore, while the odd use of the \&stringify coderef from before either sub was created does not yield a warning, with the new warning code added by my #21915 it now warns in either order of sub creation, so at least you'd be aware that something strange is afoot:
$ ./perl -Ilib -Mwarnings -e 'use builtin q(stringify); sub stringify($) {}'
Subroutine stringify redefined at -e line 1.
$ ./perl -Ilib -Mwarnings -e 'sub stringify($) {} use builtin q(stringify)'
Lexical subroutine &stringify masks previously declared package subroutine at -e line 1.
It would be good if we could warn here, but I'm not sure how practical it is.
@tonycoz this is now what #21915 does
Closing as not-a-bug