Make pos(@array) and pos(%hash) into errors
Currently pos has an effective prototype of (;\[$@%*]), and what it
does is rather interesting.
First, it produces a strange uninitialized warning:
$ ./perl -Ilib -we 'pos my @a = 3'
Use of uninitialized value within @a in scalar assignment at -e line 1.
There is no uninitialized value here. The value ‘within @a’ is actu-
ally @a itself. The code that produces the error message was written
under the (perfectly logical) assumption that an array would never be
passed to report_uninit().
Secondly, it adds pos magic to the array itself:
$ ./perl -Ilib -e 'pos @a = 3; use Devel::Peek; Dump \@a'
SV = IV(0x8039fc) at 0x803a00
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x825b90
SV = PVAV(0x804a04) at 0x825b90
REFCNT = 2
FLAGS = (SMG)
MAGIC = 0x30cb20
MG_VIRTUAL = &PL_vtbl_mglob
MG_TYPE = PERL_MAGIC_regex_global(g)
ARRAY = 0x0
FILL = -1
MAX = -1
ARYLEN = 0x0
FLAGS = (REAL)
This magic can never be used, as @a =~ /foo/g is equivalent to
scalar(@a) =~ /foo/g, and scalar(@a) returns a scalar containing the
length of the array, not the array itself.
This seems clearly a mistake.
pos forces lvalue context on its argument, making pos(3) a compile-
time error.
Internally, the main distinction between \$ (scalar lvalue) and
\[$@%*] (scalar lvalue, or some other type) prototypes is that the
function S_scalar_mod_type returns true for functions with the former,
but false for functions with the latter. (Tangentially, \[$@%*] and
\[$@%&*] are distinguished by the special-casing in op_lvalue_flags
under case OP_ENTERSUB.)
S_scalar_mod_type returns false for pos. I think it should return
true. That is what this commit does, resulting in consistency
with read():
$ ./perl -Ilib -we 'read($1, @2, $3)'
Can't modify array dereference in read at -e line 1, near "$3)
"
Execution of -e aborted due to compilation errors.
$ ./perl -Ilib -we 'pos(@2)'
Can't modify array dereference in match position at -e line 1, near "@2)
"
Execution of -e aborted due to compilation errors.
Except when it comes to globs, since read refuses *foo for its second
argument, but pos(*foo) has always Just Worked, so there is no reason
to forbid it.
So, now, pos has an effective prototype of (;\[$*]).