xref: /openbsd/gnu/usr.bin/perl/t/op/lexsub.t (revision 5dea098c)
1#!perl
2
3BEGIN {
4    chdir 't' if -d 't';
5    require './test.pl';
6    set_up_inc('../lib');
7    *bar::is = *is;
8    *bar::like = *like;
9}
10plan 151;
11
12# -------------------- our -------------------- #
13
14{
15  our sub foo { 42 }
16  is foo, 42, 'calling our sub from same package';
17  is &foo, 42, 'calling our sub from same package (amper)';
18  package bar;
19  sub bar::foo { 43 }
20  is foo, 42, 'calling our sub from another package';
21  is &foo, 42, 'calling our sub from another package (amper)';
22}
23package bar;
24is foo, 43, 'our sub falling out of scope';
25is &foo, 43, 'our sub falling out of scope (called via amper)';
26package main;
27{
28  sub bar::a { 43 }
29  our sub a {
30    if (shift) {
31      package bar;
32      is a, 43, 'our sub invisible inside itself';
33      is &a, 43, 'our sub invisible inside itself (called via amper)';
34    }
35    42
36  }
37  a(1);
38  sub bar::b { 43 }
39  our sub b;
40  our sub b {
41    if (shift) {
42      package bar;
43      is b, 42, 'our sub visible inside itself after decl';
44      is &b, 42, 'our sub visible inside itself after decl (amper)';
45    }
46    42
47  }
48  b(1)
49}
50sub c { 42 }
51sub bar::c { 43 }
52{
53  our sub c;
54  package bar;
55  is c, 42, 'our sub foo; makes lex alias for existing sub';
56  is &c, 42, 'our sub foo; makes lex alias for existing sub (amper)';
57}
58{
59  our sub d;
60  sub bar::d { 'd43' }
61  package bar;
62  sub d { 'd42' }
63  is eval ::d, 'd42', 'our sub foo; applies to subsequent sub foo {}';
64}
65{
66  our sub e ($);
67  is prototype "::e", '$', 'our sub with proto';
68}
69{
70  our sub if() { 42 }
71  my $x = if if if;
72  is $x, 42, 'lexical subs (even our) override all keywords';
73  package bar;
74  my $y = if if if;
75  is $y, 42, 'our subs from other packages override all keywords';
76}
77# Interaction with ‘use constant’
78{
79  our sub const; # symtab now has an undefined CV
80  BEGIN { delete $::{const} } # delete symtab entry; pad entry still exists
81  use constant const => 3; # symtab now has a scalar ref
82  # inlining this used to fail an assertion (parentheses necessary):
83  is(const, 3, 'our sub pointing to "use constant" constant');
84}
85# our sub and method confusion
86sub F::h { 4242 }
87{
88  my $called;
89  our sub h { ++$called; 4343 };
90  is((h F),4242, 'our sub symbol translation does not affect meth names');
91  undef $called;
92  print "#";
93  print h F; # follows a different path through yylex to intuit_method
94  print "\n";
95  is $called, undef, 'our sub symbol translation & meth names after print'
96}
97our sub j;
98is j
99  =>, 'j', 'name_of_our_sub <newline> =>  is parsed properly';
100sub _cmp { $a cmp $b }
101sub bar::_cmp { $b cmp $a }
102{
103  package bar;
104  our sub _cmp;
105  package main;
106  is join(" ", sort _cmp split //, 'oursub'), 'u u s r o b', 'sort our_sub'
107}
108
109# -------------------- state -------------------- #
110
111use feature 'state'; # state
112{
113  state sub foo { 44 }
114  isnt \&::foo, \&foo, 'state sub is not stored in the package';
115  is foo, 44, 'calling state sub from same package';
116  is &foo, 44, 'calling state sub from same package (amper)';
117  package bar;
118  is foo, 44, 'calling state sub from another package';
119  is &foo, 44, 'calling state sub from another package (amper)';
120}
121package bar;
122is foo, 43, 'state sub falling out of scope';
123is &foo, 43, 'state sub falling out of scope (called via amper)';
124{
125  sub sa { 43 }
126  state sub sa {
127    if (shift) {
128      is sa, 43, 'state sub invisible inside itself';
129      is &sa, 43, 'state sub invisible inside itself (called via amper)';
130    }
131    44
132  }
133  sa(1);
134  sub sb { 43 }
135  state sub sb;
136  state sub sb {
137    if (shift) {
138      # ‘state sub foo{}’ creates a new pad entry, not reusing the forward
139      #  declaration.  Being invisible inside itself, it sees the stub.
140      eval{sb};
141      like $@, qr/^Undefined subroutine &sb called at /,
142        'state sub foo {} after forward declaration';
143      eval{&sb};
144      like $@, qr/^Undefined subroutine &sb called at /,
145        'state sub foo {} after forward declaration (amper)';
146    }
147    44
148  }
149  sb(1);
150  sub sb2 { 43 }
151  state sub sb2;
152  sub sb2 {
153    if (shift) {
154      package bar;
155      is sb2, 44, 'state sub visible inside itself after decl';
156      is &sb2, 44, 'state sub visible inside itself after decl (amper)';
157    }
158    44
159  }
160  sb2(1);
161  state sub sb3;
162  {
163    state sub sb3 { # new pad entry
164      # The sub containing this comment is invisible inside itself.
165      # So this one here will assign to the outer pad entry:
166      sub sb3 { 47 }
167    }
168  }
169  is eval{sb3}, 47,
170    'sub foo{} applying to "state sub foo;" even inside state sub foo{}';
171  # Same test again, but inside an anonymous sub
172  sub {
173    state sub sb4;
174    {
175      state sub sb4 {
176        sub sb4 { 47 }
177      }
178    }
179    is sb4, 47,
180      'sub foo{} applying to "state sub foo;" even inside state sub foo{}';
181  }->();
182}
183sub sc { 43 }
184{
185  state sub sc;
186  eval{sc};
187  like $@, qr/^Undefined subroutine &sc called at /,
188     'state sub foo; makes no lex alias for existing sub';
189  eval{&sc};
190  like $@, qr/^Undefined subroutine &sc called at /,
191     'state sub foo; makes no lex alias for existing sub (amper)';
192}
193package main;
194{
195  state sub se ($);
196  is prototype eval{\&se}, '$', 'state sub with proto';
197  is prototype "se", undef, 'prototype "..." ignores state subs';
198}
199{
200  state sub if() { 44 }
201  my $x = if if if;
202  is $x, 44, 'state subs override all keywords';
203  package bar;
204  my $y = if if if;
205  is $y, 44, 'state subs from other packages override all keywords';
206}
207{
208  use warnings; no warnings "experimental::lexical_subs";
209  state $w ;
210  local $SIG{__WARN__} = sub { $w .= shift };
211  eval '#line 87 squidges
212    state sub foo;
213    state sub foo {};
214  ';
215  is $w,
216     '"state" subroutine &foo masks earlier declaration in same scope at '
217   . "squidges line 88.\n",
218     'warning for state sub masking earlier declaration';
219}
220# Since state vars inside anonymous subs are cloned at the same time as the
221# anonymous subs containing them, the same should happen for state subs.
222sub make_closure {
223  my $x = shift;
224  sub {
225    state sub foo { $x }
226    foo
227  }
228}
229$sub1 = make_closure 48;
230$sub2 = make_closure 49;
231is &$sub1, 48, 'state sub in closure (1)';
232is &$sub2, 49, 'state sub in closure (2)';
233# But we need to test that state subs actually do persist from one invoca-
234# tion of a named sub to another (i.e., that they are not my subs).
235{
236  use warnings; no warnings "experimental::lexical_subs";
237  state $w;
238  local $SIG{__WARN__} = sub { $w .= shift };
239  eval '#line 65 teetet
240    sub foom {
241      my $x = shift;
242      state sub poom { $x }
243      eval{\&poom}
244    }
245  ';
246  is $w, "Variable \"\$x\" will not stay shared at teetet line 67.\n",
247         'state subs get "Variable will not stay shared" messages';
248  my $poom = foom(27);
249  my $poom2 = foom(678);
250  is eval{$poom->()}, eval {$poom2->()},
251    'state subs close over the first outer my var, like pkg subs';
252  my $x = 43;
253  for $x (765) {
254    state sub etetetet { $x }
255    is eval{etetetet}, 43, 'state sub ignores for() localisation';
256  }
257}
258# And we also need to test that multiple state subs can close over each
259# other’s entries in the parent subs pad, and that cv_clone is not con-
260# fused by that.
261sub make_anon_with_state_sub{
262  sub {
263    state sub s1;
264    state sub s2 { \&s1 }
265    sub s1 { \&s2 }
266    if (@_) { return \&s1 }
267    is s1,\&s2, 'state sub in anon closure closing over sibling state sub';
268    is s2,\&s1, 'state sub in anon closure closing over sibling state sub';
269  }
270}
271{
272  my $s = make_anon_with_state_sub;
273  &$s;
274
275  # And make sure the state subs were actually cloned.
276  isnt make_anon_with_state_sub->(0), &$s(0),
277    'state subs in anon subs are cloned';
278  is &$s(0), &$s(0), 'but only when the anon sub is cloned';
279}
280# Check that nested state subs close over variables properly
281{
282  is sub {
283    state sub a;
284    state sub b {
285      state sub c {
286        state $x = 42;
287        sub a { $x }
288      }
289      c();
290    }
291    b();
292    a();
293  }->(), 42, 'state sub with body defined in doubly-nested state subs';
294  is sub {
295    state sub a;
296    state sub b;
297    state sub c {
298      sub b {
299        state $x = 42;
300        sub a { $x }
301      }
302    }
303    b();
304    a();
305  }->(), 42, 'nested state subs declared in same scope';
306  state $w;
307  local $SIG{__WARN__} = sub { $w .= shift };
308  use warnings 'closure';
309  my $sub = sub {
310    state sub a;
311    sub {
312      my $x;
313      sub a { $x }
314    }
315  };
316  like $w, qr/Variable \"\$x\" is not available at /,
317      "unavailability warning when state closure is defined in anon sub";
318}
319{
320  state sub BEGIN { exit };
321  pass 'state subs are never special blocks';
322  state sub END { shift }
323  is eval{END('jkqeudth')}, jkqeudth,
324    'state sub END {shift} implies @_, not @ARGV';
325  state sub CORE { scalar reverse shift }
326  is CORE::uc("hello"), "HELLO",
327    'lexical CORE does not interfere with CORE::...';
328}
329{
330  state sub redef {}
331  use warnings; no warnings "experimental::lexical_subs";
332  state $w;
333  local $SIG{__WARN__} = sub { $w .= shift };
334  eval "#line 56 pygpyf\nsub redef {}";
335  is $w, "Subroutine redef redefined at pygpyf line 56.\n",
336         "sub redefinition warnings from state subs";
337}
338{
339  state sub p (\@) {
340    is ref $_[0], 'ARRAY', 'state sub with proto';
341  }
342  p(my @a);
343  p my @b;
344  state sub q () { 45 }
345  is q(), 45, 'state constant called with parens';
346}
347{
348  state sub x;
349  eval 'sub x {3}';
350  is x, 3, 'state sub defined inside eval';
351
352  sub r {
353    state sub foo { 3 };
354    if (@_) { # outer call
355      r();
356      is foo(), 42,
357         'state sub run-time redefinition applies to all recursion levels';
358    }
359    else { # inner call
360      eval 'sub foo { 42 }';
361    }
362  }
363  r(1);
364}
365like runperl(
366      switches => [ '-Mfeature=lexical_subs,state' ],
367      prog     => 'state sub a { foo ref } a()',
368      stderr   => 1
369     ),
370     qr/syntax error/,
371    'referencing a state sub after a syntax error does not crash';
372{
373  state $stuff;
374  package A {
375    state sub foo{ $stuff .= our $AUTOLOAD }
376    *A::AUTOLOAD = \&foo;
377  }
378  A::bar();
379  is $stuff, 'A::bar', 'state sub assigned to *AUTOLOAD can autoload';
380}
381{
382  state sub quire{qr "quires"}
383  package o { use overload qr => \&quire }
384  ok "quires" =~ bless([], o::), 'state sub used as overload method';
385}
386{
387  state sub foo;
388  *cvgv = \&foo;
389  local *cvgv2 = *cvgv;
390  eval 'sub cvgv2 {42}'; # uses the stub already present
391  is foo, 42, 'defining state sub body via package sub declaration';
392}
393{
394  local $ENV{PERL5DB} = 'sub DB::DB{}';
395  is(
396    runperl(
397     switches => [ '-d' ],
398     progs => [ split "\n",
399      'use feature qw - lexical_subs state -;
400       no warnings q-experimental::lexical_subs-;
401       sub DB::sub{
402         print qq|4\n| unless $DB::sub =~ DESTROY;
403         goto $DB::sub
404       }
405       state sub foo {print qq|2\n|}
406       foo();
407      '
408     ],
409     stderr => 1
410    ),
411    "4\n2\n",
412    'state subs and DB::sub under -d'
413  );
414  is(
415    runperl(
416     switches => [ '-d' ],
417     progs => [ split "\n",
418      'use feature qw - lexical_subs state -;
419       no warnings q-experimental::lexical_subs-;
420       sub DB::goto{ print qq|4\n|; $_ = $DB::sub }
421       state sub foo {print qq|2\n|}
422       $^P|=0x80;
423       sub { goto &foo }->();
424       print $_ == \&foo ? qq|ok\n| : qq|$_\n|;
425      '
426     ],
427     stderr => 1
428    ),
429    "4\n2\nok\n",
430    'state subs and DB::goto under -d'
431  );
432}
433# This used to fail an assertion, but only as a standalone script
434is runperl(switches => ['-lXMfeature=:all'],
435           prog     => 'state sub x {}; undef &x; print defined &x',
436           stderr   => 1), "\n", 'undefining state sub';
437{
438  state sub x { is +(caller 0)[3], 'x', 'state sub name in caller' }
439  x
440}
441{
442  state sub _cmp { $b cmp $a }
443  is join(" ", sort _cmp split //, 'lexsub'), 'x u s l e b',
444    'sort state_sub LIST'
445}
446{
447  state sub handel { "" }
448  print handel, "ok ", curr_test(),
449       " - no 'No comma allowed' after state sub\n";
450  curr_test(curr_test()+1);
451}
452{
453  use utf8;
454  state sub φου;
455  eval { φου };
456  like $@, qr/^Undefined subroutine &φου called at /,
457    'state sub with utf8 name';
458}
459# This used to crash, but only as a standalone script
460is runperl(switches => ['-lXMfeature=:all'],
461           prog     => '$::x = global=>;
462                        sub x;
463                        sub x {
464                          state $x = 42;
465                          state sub x { print eval q|$x| }
466                          x()
467                        }
468                        x()',
469           stderr   => 1), "42\n",
470  'closure behaviour of state sub in predeclared package sub';
471
472# -------------------- my -------------------- #
473
474{
475  my sub foo { 44 }
476  isnt \&::foo, \&foo, 'my sub is not stored in the package';
477  is foo, 44, 'calling my sub from same package';
478  is &foo, 44, 'calling my sub from same package (amper)';
479  package bar;
480  is foo, 44, 'calling my sub from another package';
481  is &foo, 44, 'calling my sub from another package (amper)';
482}
483package bar;
484is foo, 43, 'my sub falling out of scope';
485is &foo, 43, 'my sub falling out of scope (called via amper)';
486{
487  sub ma { 43 }
488  my sub ma {
489    if (shift) {
490      is ma, 43, 'my sub invisible inside itself';
491      is &ma, 43, 'my sub invisible inside itself (called via amper)';
492    }
493    44
494  }
495  ma(1);
496  sub mb { 43 }
497  my sub mb;
498  my sub mb {
499    if (shift) {
500      # ‘my sub foo{}’ creates a new pad entry, not reusing the forward
501      #  declaration.  Being invisible inside itself, it sees the stub.
502      eval{mb};
503      like $@, qr/^Undefined subroutine &mb called at /,
504        'my sub foo {} after forward declaration';
505      eval{&mb};
506      like $@, qr/^Undefined subroutine &mb called at /,
507        'my sub foo {} after forward declaration (amper)';
508    }
509    44
510  }
511  mb(1);
512  sub mb2 { 43 }
513  my sub sb2;
514  sub mb2 {
515    if (shift) {
516      package bar;
517      is mb2, 44, 'my sub visible inside itself after decl';
518      is &mb2, 44, 'my sub visible inside itself after decl (amper)';
519    }
520    44
521  }
522  mb2(1);
523  my sub mb3;
524  {
525    my sub mb3 { # new pad entry
526      # The sub containing this comment is invisible inside itself.
527      # So this one here will assign to the outer pad entry:
528      sub mb3 { 47 }
529    }
530  }
531  is eval{mb3}, 47,
532    'sub foo{} applying to "my sub foo;" even inside my sub foo{}';
533  # Same test again, but inside an anonymous sub
534  sub {
535    my sub mb4;
536    {
537      my sub mb4 {
538        sub mb4 { 47 }
539      }
540    }
541    is mb4, 47,
542      'sub foo{} applying to "my sub foo;" even inside my sub foo{}';
543  }->();
544}
545sub mc { 43 }
546{
547  my sub mc;
548  eval{mc};
549  like $@, qr/^Undefined subroutine &mc called at /,
550     'my sub foo; makes no lex alias for existing sub';
551  eval{&mc};
552  like $@, qr/^Undefined subroutine &mc called at /,
553     'my sub foo; makes no lex alias for existing sub (amper)';
554}
555package main;
556{
557  my sub me ($);
558  is prototype eval{\&me}, '$', 'my sub with proto';
559  is prototype "me", undef, 'prototype "..." ignores my subs';
560
561  my $coderef = eval "my sub foo (\$\x{30cd}) {1}; \\&foo";
562  my $proto = prototype $coderef;
563  ok(utf8::is_utf8($proto), "my sub with UTF8 proto maintains the UTF8ness");
564  is($proto, "\$\x{30cd}", "check the prototypes actually match");
565}
566{
567  my sub if() { 44 }
568  my $x = if if if;
569  is $x, 44, 'my subs override all keywords';
570  package bar;
571  my $y = if if if;
572  is $y, 44, 'my subs from other packages override all keywords';
573}
574{
575  use warnings; no warnings "experimental::lexical_subs";
576  my $w ;
577  local $SIG{__WARN__} = sub { $w .= shift };
578  eval '#line 87 squidges
579    my sub foo;
580    my sub foo {};
581  ';
582  is $w,
583     '"my" subroutine &foo masks earlier declaration in same scope at '
584   . "squidges line 88.\n",
585     'warning for my sub masking earlier declaration';
586}
587# Test that my subs are cloned inside anonymous subs.
588sub mmake_closure {
589  my $x = shift;
590  sub {
591    my sub foo { $x }
592    foo
593  }
594}
595$sub1 = mmake_closure 48;
596$sub2 = mmake_closure 49;
597is &$sub1, 48, 'my sub in closure (1)';
598is &$sub2, 49, 'my sub in closure (2)';
599# Test that they are cloned in named subs.
600{
601  use warnings; no warnings "experimental::lexical_subs";
602  my $w;
603  local $SIG{__WARN__} = sub { $w .= shift };
604  eval '#line 65 teetet
605    sub mfoom {
606      my $x = shift;
607      my sub poom { $x }
608      \&poom
609    }
610  ';
611  is $w, undef, 'my subs get no "Variable will not stay shared" messages';
612  my $poom = mfoom(27);
613  my $poom2 = mfoom(678);
614  is $poom->(), 27, 'my subs closing over outer my var (1)';
615  is $poom2->(), 678, 'my subs closing over outer my var (2)';
616  my $x = 43;
617  my sub aoeu;
618  for $x (765) {
619    my sub etetetet { $x }
620    sub aoeu { $x }
621    is etetetet, 765, 'my sub respects for() localisation';
622    is aoeu, 43, 'unless it is declared outside the for loop';
623  }
624}
625# And we also need to test that multiple my subs can close over each
626# other’s entries in the parent subs pad, and that cv_clone is not con-
627# fused by that.
628sub make_anon_with_my_sub{
629  sub {
630    my sub s1;
631    my sub s2 { \&s1 }
632    sub s1 { \&s2 }
633    if (@_) { return eval { \&s1 } }
634    is eval{s1},eval{\&s2}, 'my sub in anon closure closing over sibling my sub';
635    is eval{s2},eval{\&s1}, 'my sub in anon closure closing over sibling my sub';
636  }
637}
638
639# Test my subs inside predeclared my subs
640{
641  my sub s2;
642  sub s2 {
643    my $x = 3;
644    my sub s3 { eval '$x' }
645    s3;
646  }
647  is s2, 3, 'my sub inside predeclared my sub';
648}
649
650{
651  my $s = make_anon_with_my_sub;
652  &$s;
653
654  # And make sure the my subs were actually cloned.
655  isnt make_anon_with_my_sub->(0), &$s(0),
656    'my subs in anon subs are cloned';
657  isnt &$s(0), &$s(0), 'at each invocation of the enclosing sub';
658}
659{
660  my sub BEGIN { exit };
661  pass 'my subs are never special blocks';
662  my sub END { shift }
663  is END('jkqeudth'), jkqeudth,
664    'my sub END {shift} implies @_, not @ARGV';
665}
666{
667  my sub redef {}
668  use warnings; no warnings "experimental::lexical_subs";
669  my $w;
670  local $SIG{__WARN__} = sub { $w .= shift };
671  eval "#line 56 pygpyf\nsub redef {}";
672  is $w, "Subroutine redef redefined at pygpyf line 56.\n",
673         "sub redefinition warnings from my subs";
674
675  undef $w;
676  sub {
677    my sub x {};
678    sub { eval "#line 87 khaki\n\\&x" }
679  }->()();
680  is $w, "Subroutine \"&x\" is not available at khaki line 87.\n",
681         "unavailability warning during compilation of eval in closure";
682
683  undef $w;
684  no warnings 'void';
685  eval <<'->()();';
686#line 87 khaki
687    sub {
688      my sub x{}
689      sub not_lexical8 {
690        \&x
691      }
692    }
693->()();
694  is $w, "Subroutine \"&x\" is not available at khaki line 90.\n",
695         "unavailability warning during compilation of named sub in anon";
696
697  undef $w;
698  sub not_lexical9 {
699    my sub x {};
700    format =
701@
702&x
703.
704  }
705  eval { write };
706  my($f,$l) = (__FILE__,__LINE__ - 1);
707  is $w, "Subroutine \"&x\" is not available at $f line $l.\n",
708         'unavailability warning during cloning';
709  $l -= 3;
710  is $@, "Undefined subroutine &x called at $f line $l.\n",
711         'Vivified sub is correctly named';
712}
713sub not_lexical10 {
714  my sub foo;
715  foo();
716  sub not_lexical11 {
717    my sub bar {
718      my $x = 'khaki car keys for the khaki car';
719      not_lexical10();
720      sub foo {
721       is $x, 'khaki car keys for the khaki car',
722       'mysubs in inner clonables use the running clone of their CvOUTSIDE'
723      }
724    }
725    bar()
726  }
727}
728not_lexical11();
729{
730  my sub p (\@) {
731    is ref $_[0], 'ARRAY', 'my sub with proto';
732  }
733  p(my @a);
734  p @a;
735  my sub q () { 46 }
736  is q(), 46, 'my constant called with parens';
737}
738{
739  my sub x;
740  my $count;
741  sub x { x() if $count++ < 10 }
742  x();
743  is $count, 11, 'my recursive subs';
744}
745{
746  my sub x;
747  eval 'sub x {3}';
748  is x, 3, 'my sub defined inside eval';
749
750  my sub z;
751  BEGIN { eval 'sub z {4}' }
752  is z, 4, 'my sub defined in BEGIN { eval "..." }';
753}
754
755{
756  state $w;
757  local $SIG{__WARN__} = sub { $w .= shift };
758  eval q{ my sub george () { 2 } };
759  is $w, undef, 'no double free from constant my subs';
760}
761like runperl(
762      switches => [ '-Mfeature=lexical_subs,state' ],
763      prog     => 'my sub a { foo ref } a()',
764      stderr   => 1
765     ),
766     qr/syntax error/,
767    'referencing a my sub after a syntax error does not crash';
768{
769  state $stuff;
770  package A {
771    my sub foo{ $stuff .= our $AUTOLOAD }
772    *A::AUTOLOAD = \&foo;
773  }
774  A::bar();
775  is $stuff, 'A::bar', 'my sub assigned to *AUTOLOAD can autoload';
776}
777{
778  my sub quire{qr "quires"}
779  package mo { use overload qr => \&quire }
780  ok "quires" =~ bless([], mo::), 'my sub used as overload method';
781}
782{
783  my sub foo;
784  *mcvgv = \&foo;
785  local *mcvgv2 = *mcvgv;
786  eval 'sub mcvgv2 {42}'; # uses the stub already present
787  is foo, 42, 'defining my sub body via package sub declaration';
788}
789{
790  my sub foo;
791  *mcvgv3 = \&foo;
792  local *mcvgv4 = *mcvgv3;
793  eval 'sub mcvgv4 {42}'; # uses the stub already present
794  undef *mcvgv3; undef *mcvgv4; # leaves the pad with the only reference
795}
796# We would have crashed by now if it weren’t fixed.
797pass "pad taking ownership once more of packagified my-sub";
798
799{
800  local $ENV{PERL5DB} = 'sub DB::DB{}';
801  is(
802    runperl(
803     switches => [ '-d' ],
804     progs => [ split "\n",
805      'use feature qw - lexical_subs state -;
806       no warnings q-experimental::lexical_subs-;
807       sub DB::sub{
808         print qq|4\n| unless $DB::sub =~ DESTROY;
809         goto $DB::sub
810       }
811       my sub foo {print qq|2\n|}
812       foo();
813      '
814     ],
815     stderr => 1
816    ),
817    "4\n2\n",
818    'my subs and DB::sub under -d'
819  );
820}
821# This used to fail an assertion, but only as a standalone script
822is runperl(switches => ['-lXMfeature=:all'],
823           prog     => 'my sub x {}; undef &x; print defined &x',
824           stderr   => 1), "\n", 'undefining my sub';
825{
826  my sub x { is +(caller 0)[3], 'x', 'my sub name in caller' }
827  x
828}
829{
830  my sub _cmp { $b cmp $a }
831  is join(" ", sort _cmp split //, 'lexsub'), 'x u s l e b',
832    'sort my_sub LIST'
833}
834{
835  my sub handel { "" }
836  print handel,"ok ",curr_test()," - no 'No comma allowed' after my sub\n";
837  curr_test(curr_test()+1);
838}
839{
840  my $x = 43;
841  my sub y :prototype() {$x};
842  is y, 43, 'my sub that looks like constant closure';
843}
844{
845  use utf8;
846  my sub φου;
847  eval { φου };
848  like $@, qr/^Undefined subroutine &φου called at /,
849    'my sub with utf8 name';
850}
851{
852  my $w;
853  local $SIG{__WARN__} = sub { $w = shift };
854  use warnings 'closure';
855  eval 'sub stayshared { my sub x; sub notstayshared { x } } 1' or die;
856  like $w, qr/^Subroutine "&x" will not stay shared at /,
857          'Subroutine will not stay shared';
858}
859
860# -------------------- Interactions (and misc tests) -------------------- #
861
862is sub {
863    my sub s1;
864    my sub s2 { 3 };
865    sub s1 { state sub foo { \&s2 } foo }
866    s1
867  }->()(), 3, 'state sub inside my sub closing over my sub uncle';
868
869{
870  my sub s2 { 3 };
871  sub not_lexical { state sub foo { \&s2 } foo }
872  is not_lexical->(), 3, 'state subs that reference my sub from outside';
873}
874
875# Test my subs inside predeclared package subs
876# This test also checks that CvOUTSIDE pointers are not mangled when the
877# inner sub’s CvOUTSIDE points to another sub.
878sub not_lexical2;
879sub not_lexical2 {
880  my $x = 23;
881  my sub bar;
882  sub not_lexical3 {
883    not_lexical2();
884    sub bar { $x }
885  };
886  bar
887}
888is not_lexical3, 23, 'my subs inside predeclared package subs';
889
890# Test my subs inside predeclared package sub, where the lexical sub is
891# declared outside the package sub.
892# This checks that CvOUTSIDE pointers are fixed up even when the sub is
893# not declared inside the sub that its CvOUTSIDE points to.
894sub not_lexical5 {
895  my sub foo;
896  sub not_lexical4;
897  sub not_lexical4 {
898    my $x = 234;
899    not_lexical5();
900    sub foo { $x }
901  }
902  foo
903}
904is not_lexical4, 234,
905    'my sub defined in predeclared pkg sub but declared outside';
906
907undef *not_lexical6;
908{
909  my sub foo;
910  sub not_lexical6 { sub foo { } }
911  pass 'no crash when cloning a mysub declared inside an undef pack sub';
912}
913
914undef &not_lexical7;
915eval 'sub not_lexical7 { my @x }';
916{
917  my sub foo;
918  foo();
919  sub not_lexical7 {
920    state $x;
921    sub foo {
922      is ref \$x, 'SCALAR',
923        "redeffing a mysub's outside does not make it use the wrong pad"
924    }
925  }
926}
927
928like runperl(
929      switches => [ '-Mfeature=lexical_subs,state', '-Mwarnings=FATAL,all', '-M-warnings=experimental::lexical_subs' ],
930      prog     => 'my sub foo; sub foo { foo } foo',
931      stderr   => 1
932     ),
933     qr/Deep recursion on subroutine "foo"/,
934    'deep recursion warnings for lexical subs do not crash';
935
936like runperl(
937      switches => [ '-Mfeature=lexical_subs,state', '-Mwarnings=FATAL,all', '-M-warnings=experimental::lexical_subs' ],
938      prog     => 'my sub foo() { 42 } undef &foo',
939      stderr   => 1
940     ),
941     qr/Constant subroutine foo undefined at /,
942    'constant undefinition warnings for lexical subs do not crash';
943
944{
945  my sub foo;
946  *AutoloadTestSuper::blah = \&foo;
947  sub AutoloadTestSuper::AUTOLOAD {
948    is $AutoloadTestSuper::AUTOLOAD, "AutoloadTestSuper::blah",
949      "Autoloading via inherited lex stub";
950  }
951  @AutoloadTest::ISA = AutoloadTestSuper::;
952  AutoloadTest->blah;
953}
954
955# This used to crash because op.c:find_lexical_cv was looking at the wrong
956# CV’s OUTSIDE pointer.  [perl #124099]
957{
958  my sub h; sub{my $x; sub{h}}
959}
960
961is join("-", qw(aa bb), do { my sub lleexx; 123 }, qw(cc dd)),
962  "aa-bb-123-cc-dd", 'do { my sub...} in a list [perl #132442]';
963
964{
965    # this would crash because find_lexical_cv() couldn't handle an
966    # intermediate scope which didn't include the sub
967    no warnings 'experimental::builtin';
968    use builtin 'ceil';
969    sub nested {
970        ok(eval 'ceil(1.5)', "no assertion failure calling a lexical sub from nested eval");
971    }
972    nested();
973}
974