xref: /openbsd-src/gnu/usr.bin/perl/t/op/aassign.t (revision eac174f2741a08d8deb8aae59a7f778ef9b5d770)
1b8851fccSafresh1#!./perl -w
2b8851fccSafresh1
3b8851fccSafresh1# Some miscellaneous checks for the list assignment operator, OP_AASSIGN.
4b8851fccSafresh1#
5b8851fccSafresh1# This file was only added in 2015; before then, such tests were
6b8851fccSafresh1# typically in various other random places like op/array.t. This test file
7b8851fccSafresh1# doesn't therefore attempt to be comprehensive; it merely provides a
8b8851fccSafresh1# central place to new put additional tests, especially those related to
9b8851fccSafresh1# the trickiness of commonality, e.g. ($a,$b) = ($b,$a).
10b8851fccSafresh1#
11b8851fccSafresh1# In particular, it's testing the flags
12b8851fccSafresh1#    OPpASSIGN_COMMON_SCALAR
13b8851fccSafresh1#    OPpASSIGN_COMMON_RC1
14b8851fccSafresh1#    OPpASSIGN_COMMON_AGG
15b8851fccSafresh1
16b8851fccSafresh1BEGIN {
17b8851fccSafresh1    chdir 't' if -d 't';
18b8851fccSafresh1    require './test.pl';
195759b3d2Safresh1    set_up_inc('../lib')
20b8851fccSafresh1}
21b8851fccSafresh1
22b8851fccSafresh1use warnings;
23b8851fccSafresh1use strict;
24b8851fccSafresh1
25b8851fccSafresh1# general purpose package vars
26b8851fccSafresh1
27b8851fccSafresh1our $pkg_scalar;
28b8851fccSafresh1our @pkg_array;
29b8851fccSafresh1our %pkg_hash;
30b8851fccSafresh1
31b8851fccSafresh1sub f_ret_14 { return 1..4 }
32b8851fccSafresh1
33b8851fccSafresh1# stringify a hash ref
34b8851fccSafresh1
35b8851fccSafresh1sub sh {
36b8851fccSafresh1    my $rh = $_[0];
37b8851fccSafresh1    join ',', map "$_:$rh->{$_}", sort keys %$rh;
38b8851fccSafresh1}
39b8851fccSafresh1
40b8851fccSafresh1
41b8851fccSafresh1# where the RHS has surplus elements
42b8851fccSafresh1
43b8851fccSafresh1{
44b8851fccSafresh1    my ($a,$b);
45b8851fccSafresh1    ($a,$b) = f_ret_14();
46b8851fccSafresh1    is("$a:$b", "1:2", "surplus");
47b8851fccSafresh1}
48b8851fccSafresh1
49b8851fccSafresh1# common with slices
50b8851fccSafresh1
51b8851fccSafresh1{
52b8851fccSafresh1    my @a = (1,2);
53b8851fccSafresh1    @a[0,1] = @a[1,0];
54b8851fccSafresh1    is("$a[0]:$a[1]", "2:1", "lex array slice");
55b8851fccSafresh1}
56b8851fccSafresh1
57b8851fccSafresh1# package alias
58b8851fccSafresh1
59b8851fccSafresh1{
60b8851fccSafresh1    my ($a, $b) = 1..2;
61b8851fccSafresh1    for $pkg_scalar ($a) {
62b8851fccSafresh1        ($pkg_scalar, $b) = (3, $a);
63b8851fccSafresh1        is($pkg_scalar, 3, "package alias pkg");
64b8851fccSafresh1        is("$a:$b", "3:1", "package alias a:b");
65b8851fccSafresh1    }
66b8851fccSafresh1}
67b8851fccSafresh1
68b8851fccSafresh1# my array/hash populated via closure
69b8851fccSafresh1
70b8851fccSafresh1{
71b8851fccSafresh1    my $ra = f1();
72b8851fccSafresh1    my ($x, @a) = @$ra;
73b8851fccSafresh1    sub f1 { $x = 1; @a = 2..4; \@a }
74b8851fccSafresh1    is($x,       2, "my: array closure x");
75b8851fccSafresh1    is("@a", "3 4", "my: array closure a");
76b8851fccSafresh1
77b8851fccSafresh1    my $rh = f2();
78b8851fccSafresh1    my ($k, $v, %h) = (d => 4, %$rh, e => 6);
79b8851fccSafresh1    sub f2 { $k = 'a'; $v = 1; %h = qw(b 2 c 3); \%h }
80b8851fccSafresh1    is("$k:$v", "d:4", "my: hash closure k:v");
81b8851fccSafresh1    is(sh(\%h), "b:2,c:3,e:6", "my: hash closure h");
82b8851fccSafresh1}
83b8851fccSafresh1
84b8851fccSafresh1
85b8851fccSafresh1# various shared element scenarios within a my (...)
86b8851fccSafresh1
87b8851fccSafresh1{
88b8851fccSafresh1    my ($x,$y) = f3(); # $x and $y on both sides
89b8851fccSafresh1    sub f3 : lvalue { ($x,$y) = (1,2); $y, $x }
90b8851fccSafresh1    is ("$x:$y", "2:1", "my: scalar and lvalue sub");
91b8851fccSafresh1}
92b8851fccSafresh1
93b8851fccSafresh1{
94b8851fccSafresh1    my $ra = f4();
95b8851fccSafresh1    my @a = @$ra;  # elements of @a on both sides
96b8851fccSafresh1    sub f4 { @a = 1..4; \@a }
97b8851fccSafresh1    is("@a", "1 2 3 4", "my: array and elements");
98b8851fccSafresh1}
99b8851fccSafresh1
100b8851fccSafresh1{
101b8851fccSafresh1    my $rh = f5();
102b8851fccSafresh1    my %h = %$rh;  # elements of %h on both sides
103b8851fccSafresh1    sub f5 { %h = qw(a 1 b 2 c 3); \%h }
104b8851fccSafresh1    is(sh(\%h), "a:1,b:2,c:3", "my: hash and elements");
105b8851fccSafresh1}
106b8851fccSafresh1
107b8851fccSafresh1{
108b8851fccSafresh1    f6();
109b8851fccSafresh1    our $xalias6;
110b8851fccSafresh1    my ($x, $y) = (2, $xalias6);
111b8851fccSafresh1    sub f6 { $x = 1; *xalias6 = \$x; }
112b8851fccSafresh1    is ("$x:$y", "2:1", "my: pkg var aliased to lexical");
113b8851fccSafresh1}
114b8851fccSafresh1
115b8851fccSafresh1
116b8851fccSafresh1{
117b8851fccSafresh1    my @a;
118b8851fccSafresh1    f7();
119b8851fccSafresh1    my ($x,$y) = @a;
120b8851fccSafresh1    is ("$x:$y", "2:1", "my: lex array elements aliased");
121b8851fccSafresh1
122b8851fccSafresh1    sub f7 {
123b8851fccSafresh1        ($x, $y) = (1,2);
124b8851fccSafresh1        use feature 'refaliasing';
125b8851fccSafresh1        no warnings 'experimental';
126b8851fccSafresh1        \($a[0], $a[1]) = \($y,$x);
127b8851fccSafresh1    }
128b8851fccSafresh1}
129b8851fccSafresh1
130b8851fccSafresh1{
131b8851fccSafresh1    @pkg_array = ();
132b8851fccSafresh1    f8();
133b8851fccSafresh1    my ($x,$y) = @pkg_array;
134b8851fccSafresh1    is ("$x:$y", "2:1", "my: pkg array elements aliased");
135b8851fccSafresh1
136b8851fccSafresh1    sub f8 {
137b8851fccSafresh1        ($x, $y) = (1,2);
138b8851fccSafresh1        use feature 'refaliasing';
139b8851fccSafresh1        no warnings 'experimental';
140b8851fccSafresh1        \($pkg_array[0], $pkg_array[1]) = \($y,$x);
141b8851fccSafresh1    }
142b8851fccSafresh1}
143b8851fccSafresh1
144b8851fccSafresh1{
145b8851fccSafresh1    f9();
146b8851fccSafresh1    my ($x,$y) = f9();
147b8851fccSafresh1    is ("$x:$y", "2:1", "my: pkg scalar alias");
148b8851fccSafresh1
149b8851fccSafresh1    our $xalias9;
150b8851fccSafresh1    sub f9 : lvalue {
151b8851fccSafresh1        ($x, $y) = (1,2);
152b8851fccSafresh1        *xalias9 = \$x;
153b8851fccSafresh1        $y, $xalias9;
154b8851fccSafresh1    }
155b8851fccSafresh1}
156b8851fccSafresh1
157b8851fccSafresh1{
158b8851fccSafresh1    use feature 'refaliasing';
159b8851fccSafresh1    no warnings 'experimental';
160b8851fccSafresh1
161b8851fccSafresh1    f10();
162b8851fccSafresh1    our $pkg10;
163b8851fccSafresh1    \(my $lex) = \$pkg10;
164b8851fccSafresh1    my @a = ($lex,3); # equivalent to ($a[0],3)
165b8851fccSafresh1    is("@a", "1 3", "my: lex alias of array alement");
166b8851fccSafresh1
167b8851fccSafresh1    sub f10 {
168b8851fccSafresh1        @a = (1,2);
169b8851fccSafresh1        \$pkg10 = \$a[0];
170b8851fccSafresh1    }
171b8851fccSafresh1
172b8851fccSafresh1}
173b8851fccSafresh1
174b8851fccSafresh1{
175b8851fccSafresh1    use feature 'refaliasing';
176b8851fccSafresh1    no warnings 'experimental';
177b8851fccSafresh1
178b8851fccSafresh1    f11();
179b8851fccSafresh1    my @b;
180b8851fccSafresh1    my @a = (@b);
181b8851fccSafresh1    is("@a", "2 1", "my: lex alias of array alements");
182b8851fccSafresh1
183b8851fccSafresh1    sub f11 {
184b8851fccSafresh1        @a = (1,2);
185b8851fccSafresh1        \$b[0] = \$a[1];
186b8851fccSafresh1        \$b[1] = \$a[0];
187b8851fccSafresh1    }
188b8851fccSafresh1}
189b8851fccSafresh1
190b8851fccSafresh1# package aliasing
191b8851fccSafresh1
192b8851fccSafresh1{
193b8851fccSafresh1    my ($x, $y) = (1,2);
194b8851fccSafresh1
195b8851fccSafresh1    for $pkg_scalar ($x) {
196b8851fccSafresh1        ($pkg_scalar, $y) = (3, $x);
197b8851fccSafresh1        is("$pkg_scalar,$y", "3,1", "package scalar aliased");
198b8851fccSafresh1    }
199b8851fccSafresh1}
200b8851fccSafresh1
201b8851fccSafresh1# lvalue subs on LHS
202b8851fccSafresh1
203b8851fccSafresh1{
204b8851fccSafresh1    my @a;
205b8851fccSafresh1    sub f12 : lvalue { @a }
206b8851fccSafresh1    (f12()) = 1..3;
207b8851fccSafresh1    is("@a", "1 2 3", "lvalue sub on RHS returns array");
208b8851fccSafresh1}
209b8851fccSafresh1
210b8851fccSafresh1{
211b8851fccSafresh1    my ($x,$y);
212b8851fccSafresh1    sub f13 : lvalue { $x,$y }
213b8851fccSafresh1    (f13()) = 1..3;
214b8851fccSafresh1    is("$x:$y", "1:2", "lvalue sub on RHS returns scalars");
215b8851fccSafresh1}
216b8851fccSafresh1
217b8851fccSafresh1
218b8851fccSafresh1# package shared scalar vars
219b8851fccSafresh1
220b8851fccSafresh1{
221b8851fccSafresh1    our $pkg14a = 1;
222b8851fccSafresh1    our $pkg14b = 2;
223b8851fccSafresh1    ($pkg14a,$pkg14b) = ($pkg14b,$pkg14a);
224b8851fccSafresh1    is("$pkg14a:$pkg14b", "2:1", "shared package scalars");
225b8851fccSafresh1}
226b8851fccSafresh1
227b8851fccSafresh1# lexical shared scalar vars
228b8851fccSafresh1
229b8851fccSafresh1{
230b8851fccSafresh1    my $a = 1;
231b8851fccSafresh1    my $b = 2;
232b8851fccSafresh1    ($a,$b) = ($b,$a);
233b8851fccSafresh1    is("$a:$b", "2:1", "shared lexical scalars");
234b8851fccSafresh1}
235b8851fccSafresh1
236b8851fccSafresh1
237b8851fccSafresh1# lexical nested array elem swap
238b8851fccSafresh1
239b8851fccSafresh1{
240b8851fccSafresh1    my @a;
241b8851fccSafresh1    $a[0][0] = 1;
242b8851fccSafresh1    $a[0][1] = 2;
243b8851fccSafresh1    ($a[0][0],$a[0][1]) =  ($a[0][1],$a[0][0]);
244b8851fccSafresh1    is("$a[0][0]:$a[0][1]", "2:1", "lexical nested array elem swap");
245b8851fccSafresh1}
246b8851fccSafresh1
247b8851fccSafresh1# package nested array elem swap
248b8851fccSafresh1
249b8851fccSafresh1{
250b8851fccSafresh1    our @a15;
251b8851fccSafresh1    $a15[0][0] = 1;
252b8851fccSafresh1    $a15[0][1] = 2;
253b8851fccSafresh1    ($a15[0][0],$a15[0][1]) =  ($a15[0][1],$a15[0][0]);
254b8851fccSafresh1    is("$a15[0][0]:$a15[0][1]", "2:1", "package nested array elem swap");
255b8851fccSafresh1}
256b8851fccSafresh1
257b8851fccSafresh1# surplus RHS junk
258b8851fccSafresh1#
259b8851fccSafresh1{
260b8851fccSafresh1    our ($a16, $b16);
261b8851fccSafresh1    ($a16, undef, $b16) = 1..30;
262b8851fccSafresh1    is("$a16:$b16", "1:3", "surplus RHS junk");
263b8851fccSafresh1}
264b8851fccSafresh1
265b8851fccSafresh1# my ($scalar,....) = @_
266b8851fccSafresh1#
267b8851fccSafresh1# technically this is an unsafe usage commonality-wise, but
268b8851fccSafresh1# a) you have to try really hard to break it, as this test shows;
269b8851fccSafresh1# b) it's such an important usage that for performance reasons we
270b8851fccSafresh1#    mark it as safe even though it isn't really. Hence it's a TODO.
271b8851fccSafresh1
272b8851fccSafresh1SKIP: {
273b8851fccSafresh1    use Config;
274b8851fccSafresh1    # debugging builds will detect this failure and panic
2755759b3d2Safresh1    skip "DEBUGGING build" if $::Config{ccflags} =~ /(?<!\S)-DDEBUGGING(?!\S)/
276b8851fccSafresh1                              or $^O eq 'VMS' && $::Config{usedebugging_perl} eq 'Y';
277b8851fccSafresh1    local $::TODO = 'cheat and optimise my (....) = @_';
278b8851fccSafresh1    local @_ = 1..3;
279b8851fccSafresh1    &f17;
280b8851fccSafresh1    my ($a, @b) = @_;
281b8851fccSafresh1    is("($a)(@b)", "(3)(2 1)", 'my (....) = @_');
282b8851fccSafresh1
283b8851fccSafresh1    sub f17 {
284b8851fccSafresh1        use feature 'refaliasing';
285b8851fccSafresh1        no warnings 'experimental';
286b8851fccSafresh1        ($a, @b) = @_;
287b8851fccSafresh1        \($_[2], $_[1], $_[0]) = \($a, $b[0], $b[1]);
288b8851fccSafresh1    }
289b8851fccSafresh1}
290b8851fccSafresh1
291b8851fccSafresh1# single scalar on RHS that's in an aggregate on LHS
292b8851fccSafresh1
293b8851fccSafresh1{
294b8851fccSafresh1    my @a = 1..3;
295b8851fccSafresh1    for my $x ($a[0]) {
296b8851fccSafresh1        (@a) = ($x);
297b8851fccSafresh1        is ("(@a)", "(1)", 'single scalar on RHS, agg');
298b8851fccSafresh1    }
299b8851fccSafresh1}
300b8851fccSafresh1
301b8851fccSafresh1# TEMP buffer stealing.
302b8851fccSafresh1# In something like
303b8851fccSafresh1#    (...) = (f())[0,0]
304b8851fccSafresh1# the same TEMP RHS element may be used more than once, so when copying
305b8851fccSafresh1# it, we mustn't steal its buffer.
3065759b3d2Safresh1# DAPM 10/2016 - but in that case the SvTEMP flag is sometimes getting
3075759b3d2Safresh1# cleared: using split() instead as a source of temps seems more reliable,
3085759b3d2Safresh1# so I've added splut variants too.
309b8851fccSafresh1
310b8851fccSafresh1{
311b8851fccSafresh1    # a string long enough for COW and buffer stealing to be enabled
312b8851fccSafresh1    my $long = 'def' . ('x' x 2000);
313b8851fccSafresh1
314b8851fccSafresh1    # a sub that is intended to return a TEMP string that isn't COW
315b8851fccSafresh1    # the concat returns a non-COW PADTMP; pp_leavesub sees a long
316b8851fccSafresh1    # stealable string, so creates a TEMP with the stolen buffer from the
3175759b3d2Safresh1    # PADTMP - hence it returns a non-COW string. It also returns a couple
3185759b3d2Safresh1    # of key strings for the hash tests
319b8851fccSafresh1    sub f18 {
320b8851fccSafresh1        my $x = "abc";
3215759b3d2Safresh1        ($x . $long, "key1", "key2");
322b8851fccSafresh1    }
323b8851fccSafresh1
3245759b3d2Safresh1    my (@a, %h);
325b8851fccSafresh1
326b8851fccSafresh1    # with @a initially empty,the code path creates a new copy of each
327b8851fccSafresh1    # RHS element to store in the array
328b8851fccSafresh1
329b8851fccSafresh1    @a = (f18())[0,0];
3305759b3d2Safresh1    is (substr($a[0], 0, 7), "abcdefx", 'NOSTEAL f18 empty $a[0]');
3315759b3d2Safresh1    is (substr($a[1], 0, 7), "abcdefx", 'NOSTEAL f18 empty $a[1]');
3325759b3d2Safresh1    @a = (split /-/, "abc-def")[0,0];
3335759b3d2Safresh1    is ($a[0], "abc", 'NOSTEAL split empty $a[0]');
3345759b3d2Safresh1    is ($a[1], "abc", 'NOSTEAL split empty $a[1]');
335b8851fccSafresh1
336b8851fccSafresh1    # with @a initially non-empty, it takes a different code path that
337b8851fccSafresh1    # makes a mortal copy of each RHS element
338b8851fccSafresh1    @a = 1..3;
339b8851fccSafresh1    @a = (f18())[0,0];
3405759b3d2Safresh1    is (substr($a[0], 0, 7), "abcdefx", 'NOSTEAL f18 non-empty $a[0]');
3415759b3d2Safresh1    is (substr($a[1], 0, 7), "abcdefx", 'NOSTEAL f18 non-empty $a[1]');
3425759b3d2Safresh1    @a = 1..3;
3435759b3d2Safresh1    @a = (split /-/, "abc-def")[0,0];
3445759b3d2Safresh1    is ($a[0], "abc", 'NOSTEAL split non-empty $a[0]');
3455759b3d2Safresh1    is ($a[1], "abc", 'NOSTEAL split non-empty $a[1]');
346b8851fccSafresh1
3475759b3d2Safresh1    # similarly with PADTMPs
3485759b3d2Safresh1
3495759b3d2Safresh1    @a = ();
3505759b3d2Safresh1    @a = ($long . "x")[0,0];
3515759b3d2Safresh1    is (substr($a[0], 0, 4), "defx", 'NOSTEAL PADTMP empty $a[0]');
3525759b3d2Safresh1    is (substr($a[1], 0, 4), "defx", 'NOSTEAL PADTMP empty $a[1]');
3535759b3d2Safresh1
3545759b3d2Safresh1    @a = 1..3;
3555759b3d2Safresh1    @a = ($long . "x")[0,0];
3565759b3d2Safresh1    is (substr($a[0], 0, 4), "defx", 'NOSTEAL PADTMP non-empty $a[0]');
3575759b3d2Safresh1    is (substr($a[1], 0, 4), "defx", 'NOSTEAL PADTMP non-empty $a[1]');
3585759b3d2Safresh1
3595759b3d2Safresh1    #  as above, but assigning to a hash
3605759b3d2Safresh1
3615759b3d2Safresh1    %h = (f18())[1,0,2,0];
3625759b3d2Safresh1    is (substr($h{key1}, 0, 7), "abcdefx", 'NOSTEAL f18 empty $h{key1}');
3635759b3d2Safresh1    is (substr($h{key2}, 0, 7), "abcdefx", 'NOSTEAL f18 empty $h{key2}');
3645759b3d2Safresh1    %h = (split /-/, "key1-val-key2")[0,1,2,1];
3655759b3d2Safresh1    is ($h{key1}, "val", 'NOSTEAL split empty $h{key1}');
3665759b3d2Safresh1    is ($h{key2}, "val", 'NOSTEAL split empty $h{key2}');
3675759b3d2Safresh1
3685759b3d2Safresh1    %h = qw(key1 foo key2 bar key3 baz);
3695759b3d2Safresh1    %h = (f18())[1,0,2,0];
3705759b3d2Safresh1    is (substr($h{key1}, 0, 7), "abcdefx", 'NOSTEAL f18 non-empty $h{key1}');
3715759b3d2Safresh1    is (substr($h{key2}, 0, 7), "abcdefx", 'NOSTEAL f18 non-empty $h{key2}');
3725759b3d2Safresh1    %h = qw(key1 foo key2 bar key3 baz);
3735759b3d2Safresh1    %h = (split /-/, "key1-val-key2")[0,1,2,1];
3745759b3d2Safresh1    is ($h{key1}, "val", 'NOSTEAL split non-empty $h{key1}');
3755759b3d2Safresh1    is ($h{key2}, "val", 'NOSTEAL split non-empty $h{key2}');
3765759b3d2Safresh1
3775759b3d2Safresh1    %h = ();
3785759b3d2Safresh1    %h = ($long . "x", "key1", "key2")[1,0,2,0];
3795759b3d2Safresh1    is (substr($h{key1}, 0, 4), "defx", 'NOSTEAL PADTMP empty $h{key1}');
3805759b3d2Safresh1    is (substr($h{key2}, 0, 4), "defx", 'NOSTEAL PADTMP empty $h{key2}');
3815759b3d2Safresh1
3825759b3d2Safresh1    %h = qw(key1 foo key2 bar key3 baz);
3835759b3d2Safresh1    %h = ($long . "x", "key1", "key2")[1,0,2,0];
3845759b3d2Safresh1    is (substr($h{key1}, 0, 4), "defx", 'NOSTEAL PADTMP non-empty $h{key1}');
3855759b3d2Safresh1    is (substr($h{key2}, 0, 4), "defx", 'NOSTEAL PADTMP non-empty $h{key2}');
3865759b3d2Safresh1
3875759b3d2Safresh1    # both keys and values stealable
3885759b3d2Safresh1    @a = (%h = (split /-/, "abc-def")[0,1,0,1]);
389*eac174f2Safresh1    is (join(':', keys   %h), "abc",     "NOSTEAL split list-context keys");
390*eac174f2Safresh1    is (join(':', values %h), "def",     "NOSTEAL split list-context values");
391*eac174f2Safresh1    is (join(':', @a),        "abc:def", "NOSTEAL split list-context result");
392b8851fccSafresh1}
393b8851fccSafresh1
394b8851fccSafresh1{
395b8851fccSafresh1    my $x = 1;
396b8851fccSafresh1    my $y = 2;
397b8851fccSafresh1    ($x,$y) = (undef, $x);
398b8851fccSafresh1    is($x, undef, 'single scalar on RHS, but two on LHS: x');
399b8851fccSafresh1    is($y, 1, 'single scalar on RHS, but two on LHS: y');
400b8851fccSafresh1}
401b8851fccSafresh1
402b8851fccSafresh1{ # magic handling, see #126633
403b8851fccSafresh1    use v5.22;
404b8851fccSafresh1    my $set;
405b8851fccSafresh1    package ArrayProxy {
406b8851fccSafresh1        sub TIEARRAY { bless [ $_[1] ] }
407b8851fccSafresh1        sub STORE { $_[0][0]->[$_[1]] = $_[2]; $set = 1 }
408b8851fccSafresh1        sub FETCH { $_[0][0]->[$_[1]] }
409b8851fccSafresh1        sub CLEAR { @{$_[0][0]} = () }
410b8851fccSafresh1        sub EXTEND {}
411b8851fccSafresh1    };
412b8851fccSafresh1    my @base = ( "a", "b" );
413b8851fccSafresh1    my @real = @base;
414b8851fccSafresh1    my @proxy;
415b8851fccSafresh1    my $temp;
416b8851fccSafresh1    tie @proxy, "ArrayProxy", \@real;
417b8851fccSafresh1    @proxy[0, 1] = @real[1, 0];
418b8851fccSafresh1    is($real[0], "b", "tied left first");
419b8851fccSafresh1    is($real[1], "a", "tied left second");
420b8851fccSafresh1    @real = @base;
421b8851fccSafresh1    @real[0, 1] = @proxy[1, 0];
422b8851fccSafresh1    is($real[0], "b", "tied right first");
423b8851fccSafresh1    is($real[1], "a", "tied right second");
424b8851fccSafresh1    @real = @base;
425b8851fccSafresh1    @proxy[0, 1] = @proxy[1, 0];
426b8851fccSafresh1    is($real[0], "b", "tied both first");
427b8851fccSafresh1    is($real[1], "a", "tied both second");
428b8851fccSafresh1    @real = @base;
429b8851fccSafresh1    ($temp, @real) = @proxy[1, 0];
430b8851fccSafresh1    is($real[0], "a", "scalar/array tied right");
431b8851fccSafresh1    @real = @base;
432b8851fccSafresh1    ($temp, @proxy) = @real[1, 0];
433b8851fccSafresh1    is($real[0], "a", "scalar/array tied left");
434b8851fccSafresh1    @real = @base;
435b8851fccSafresh1    ($temp, @proxy) = @proxy[1, 0];
436b8851fccSafresh1    is($real[0], "a", "scalar/array tied both");
437b8851fccSafresh1    $set = 0;
438b8851fccSafresh1    my $orig;
439b8851fccSafresh1    ($proxy[0], $orig) = (1, $set);
440b8851fccSafresh1    is($orig, 0, 'previous value of $set');
441b8851fccSafresh1
442b8851fccSafresh1    # from cpan #110278
443b8851fccSafresh1  SKIP: {
444b8851fccSafresh1      skip "no List::Util::min on miniperl", 2, if is_miniperl;
445b8851fccSafresh1      require List::Util;
446b8851fccSafresh1      my $x = 1;
447b8851fccSafresh1      my $y = 2;
448b8851fccSafresh1      ( $x, $y ) = ( List::Util::min($y), List::Util::min($x) );
449b8851fccSafresh1      is($x, 2, "check swap for \$x");
450b8851fccSafresh1      is($y, 1, "check swap for \$y");
451b8851fccSafresh1    }
452b8851fccSafresh1}
453b8851fccSafresh1
4545759b3d2Safresh1{
4555759b3d2Safresh1    # check that a second aggregate is empted but doesn't suck up
4565759b3d2Safresh1    # anything random
4575759b3d2Safresh1
4585759b3d2Safresh1    my (@a, @b) = qw(x y);
4595759b3d2Safresh1    is(+@a, 2, "double array A len");
4605759b3d2Safresh1    is(+@b, 0, "double array B len");
4615759b3d2Safresh1    is("@a", "x y", "double array A contents");
4625759b3d2Safresh1
4635759b3d2Safresh1    @a = 1..10;
4645759b3d2Safresh1    @b = 100..200;
4655759b3d2Safresh1    (@a, @b) = qw(x y);
4665759b3d2Safresh1    is(+@a, 2, "double array non-empty A len");
4675759b3d2Safresh1    is(+@b, 0, "double array non-empty B len");
4685759b3d2Safresh1    is("@a", "x y", "double array non-empty A contents");
4695759b3d2Safresh1
4705759b3d2Safresh1    my (%a, %b) = qw(k1 v1 k2 v2);
4715759b3d2Safresh1    is(+(keys %a), 2, "double hash A len");
4725759b3d2Safresh1    is(+(keys %b), 0, "double hash B len");
4735759b3d2Safresh1    is(join(' ', sort keys   %a), "k1 k2", "double hash A keys");
4745759b3d2Safresh1    is(join(' ', sort values %a), "v1 v2", "double hash A values");
4755759b3d2Safresh1
4765759b3d2Safresh1    %a = 1..10;
4775759b3d2Safresh1    %b = 101..200;
4785759b3d2Safresh1    (%a, %b) = qw(k1 v1 k2 v2);
4795759b3d2Safresh1    is(+(keys %a), 2, "double hash non-empty A len");
4805759b3d2Safresh1    is(+(keys %b), 0, "double hash non-empty B len");
4815759b3d2Safresh1    is(join(' ', sort keys   %a), "k1 k2", "double hash non-empty A keys");
4825759b3d2Safresh1    is(join(' ', sort values %a), "v1 v2", "double hash non-empty A values");
4835759b3d2Safresh1}
4845759b3d2Safresh1
4855759b3d2Safresh1#  list and lval context: filling of missing elements, returning correct
4865759b3d2Safresh1#  lvalues.
4875759b3d2Safresh1#  ( Note that these partially duplicate some tests in hashassign.t which
4885759b3d2Safresh1#  I didn't spot at first - DAPM)
4895759b3d2Safresh1
4905759b3d2Safresh1{
4915759b3d2Safresh1    my ($x, $y, $z);
4925759b3d2Safresh1    my (@a, %h);
4935759b3d2Safresh1
4945759b3d2Safresh1    sub lval {
4955759b3d2Safresh1        my $n    = shift;
4965759b3d2Safresh1        my $desc = shift;
4975759b3d2Safresh1        is($x, $n >= 1 ? "assign1" : undef, "lval: X pre $n $desc");
4985759b3d2Safresh1        is($y, $n >= 2 ? "assign2" : undef, "lval: Y pre $n $desc");
4995759b3d2Safresh1        is($z,                       undef, "lval: Z pre $n $desc");
5005759b3d2Safresh1
5015759b3d2Safresh1        my $i = 0;
5025759b3d2Safresh1        for (@_) {
5035759b3d2Safresh1            $_ = "lval$i";
5045759b3d2Safresh1            $i++;
5055759b3d2Safresh1        }
5065759b3d2Safresh1        is($x, "lval0", "lval: a post $n $desc");
5075759b3d2Safresh1        is($y, "lval1", "lval: b post $n $desc");
5085759b3d2Safresh1        is($z, "lval2", "lval: c post $n $desc");
5095759b3d2Safresh1    }
5105759b3d2Safresh1    lval(0, "XYZ", (($x,$y,$z) = ()));
5115759b3d2Safresh1    lval(1, "XYZ", (($x,$y,$z) = (qw(assign1))));
5125759b3d2Safresh1    lval(2, "XYZ", (($x,$y,$z) = (qw(assign1 assign2))));
5135759b3d2Safresh1
5145759b3d2Safresh1    lval(0, "XYZA", (($x,$y,$z,@a) = ()));
5155759b3d2Safresh1    lval(1, "XYZA", (($x,$y,$z,@a) = (qw(assign1))));
5165759b3d2Safresh1    lval(2, "XYZA", (($x,$y,$z,@a) = (qw(assign1 assign2))));
5175759b3d2Safresh1
5185759b3d2Safresh1    lval(0, "XYAZ", (($x,$y,@a,$z) = ()));
5195759b3d2Safresh1    lval(1, "XYAZ", (($x,$y,@a,$z) = (qw(assign1))));
5205759b3d2Safresh1    lval(2, "XYAZ", (($x,$y,@a,$z) = (qw(assign1 assign2))));
5215759b3d2Safresh1
5225759b3d2Safresh1    lval(0, "XYZH", (($x,$y,$z,%h) = ()));
5235759b3d2Safresh1    lval(1, "XYZH", (($x,$y,$z,%h) = (qw(assign1))));
5245759b3d2Safresh1    lval(2, "XYZH", (($x,$y,$z,%h) = (qw(assign1 assign2))));
5255759b3d2Safresh1
5265759b3d2Safresh1    lval(0, "XYHZ", (($x,$y,%h,$z) = ()));
5275759b3d2Safresh1    lval(1, "XYHZ", (($x,$y,%h,$z) = (qw(assign1))));
5285759b3d2Safresh1    lval(2, "XYHZ", (($x,$y,%h,$z) = (qw(assign1 assign2))));
5295759b3d2Safresh1
5305759b3d2Safresh1    # odd number of hash elements
5315759b3d2Safresh1
5325759b3d2Safresh1    {
5335759b3d2Safresh1        no warnings 'misc';
5345759b3d2Safresh1        @a = ((%h) = qw(X));
5355759b3d2Safresh1        is (join(":", map $_ // "u", @a), "X:u",      "lval odd singleton");
5365759b3d2Safresh1        @a = (($x, $y, %h) = qw(X Y K));
5375759b3d2Safresh1        is (join(":", map $_ // "u", @a), "X:Y:K:u",   "lval odd");
5385759b3d2Safresh1        @a = (($x, $y, %h, $z) = qw(X Y K));
5395759b3d2Safresh1        is (join(":", map $_ // "u", @a), "X:Y:K:u:u", "lval odd with z");
5405759b3d2Safresh1    }
5415759b3d2Safresh1
5425759b3d2Safresh1    # undef on LHS uses RHS as lvalue instead
54356d68f1eSafresh1    # Note that this just codifies existing behaviour - it may not be
5445759b3d2Safresh1    # correct. See http://nntp.perl.org/group/perl.perl5.porters/240358.
5455759b3d2Safresh1
5465759b3d2Safresh1    {
5475759b3d2Safresh1        ($x, $y, $z)  = (0, 10, 20);
5485759b3d2Safresh1        $_++ for ((undef, $x) = ($y, $z));
5495759b3d2Safresh1        is "$x:$y:$z", "21:11:20", "undef as lvalue";
5505759b3d2Safresh1    }
5515759b3d2Safresh1
5525759b3d2Safresh1}
5535759b3d2Safresh1
5545759b3d2Safresh1{
5555759b3d2Safresh1    # [perl #129991] assert failure in S_aassign_copy_common
5565759b3d2Safresh1    # the LHS of a list assign can be aliased to an immortal SV;
5575759b3d2Safresh1    # we used to assert that this couldn't happen
5585759b3d2Safresh1    eval { ($_,$0)=(1,0) for 0 gt 0 };
5595759b3d2Safresh1    like($@, qr//, "RT #129991");
5605759b3d2Safresh1}
5615759b3d2Safresh1
5625759b3d2Safresh1{
5635759b3d2Safresh1    # [perl #130132]
5645759b3d2Safresh1    # lexical refs on LHS, dereffed on the RHS
5655759b3d2Safresh1
5665759b3d2Safresh1    my $fill;
5675759b3d2Safresh1
5685759b3d2Safresh1    my $sref = do { my $tmp = 2; \$tmp };
5695759b3d2Safresh1    ($sref, $fill) = (1, $$sref);
5705759b3d2Safresh1    is ($sref, 1, "RT #130132 scalar 1");
5715759b3d2Safresh1    is ($fill, 2, "RT #130132 scalar 2");
5725759b3d2Safresh1
5735759b3d2Safresh1    my $x = 1;
5745759b3d2Safresh1    $sref = \$x;
5755759b3d2Safresh1    ($sref, $$sref) = (2, 3);
5765759b3d2Safresh1    is ($sref, 2, "RT #130132 scalar derefffed 1");
5775759b3d2Safresh1    is ($x,    3, "RT #130132 scalar derefffed 2");
5785759b3d2Safresh1
5795759b3d2Safresh1    $x = 1;
5805759b3d2Safresh1    $sref = \$x;
5815759b3d2Safresh1    ($sref, $$sref) = (2);
5825759b3d2Safresh1    is ($sref, 2,     "RT #130132 scalar undef 1");
5835759b3d2Safresh1    is ($x,    undef, "RT #130132 scalar undef 2");
5845759b3d2Safresh1
5855759b3d2Safresh1    my @a;
5865759b3d2Safresh1    $sref = do { my $tmp = 2; \$tmp };
5875759b3d2Safresh1    @a = (($sref) = (1, $$sref));
5885759b3d2Safresh1    is ($sref, 1,     "RT #130132 scalar list cxt 1");
5895759b3d2Safresh1    is ($a[0], 1,     "RT #130132 scalar list cxt a[0]");
5905759b3d2Safresh1
5915759b3d2Safresh1    my $aref = [ 1, 2 ];
5925759b3d2Safresh1    ($aref, $fill) = @$aref;
5935759b3d2Safresh1    is ($aref, 1, "RT #130132 array 1");
5945759b3d2Safresh1    is ($fill, 2, "RT #130132 array 2");
5955759b3d2Safresh1}
5965759b3d2Safresh1
59756d68f1eSafresh1{
598*eac174f2Safresh1    # GH #17816
59956d68f1eSafresh1    # don't use the "1-arg on LHS can't be common" optimisation
60056d68f1eSafresh1    # when there are undef's there
60156d68f1eSafresh1    my $x = 1;
60256d68f1eSafresh1    my @a = (($x, undef) = (2 => $x));
60356d68f1eSafresh1    is("@a", "2 1", "GH #17816");
60456d68f1eSafresh1}
60556d68f1eSafresh1
60656d68f1eSafresh1{
607*eac174f2Safresh1    # GH #16685
60856d68f1eSafresh1    # honour trailing undef's in list context
60956d68f1eSafresh1    my $x = 1;
61056d68f1eSafresh1    my @a = (($x, undef, undef) = (1));
611*eac174f2Safresh1    is(scalar @a, 3, "GH #16685");
61256d68f1eSafresh1}
61356d68f1eSafresh1
61456d68f1eSafresh1
615b8851fccSafresh1done_testing();
616