Implement scheduled fatalization of my() in false conditional
authorJames E Keenan <jkeenan@cpan.org>
Tue, 25 Sep 2018 19:28:46 +0000 (15:28 -0400)
committerJames E Keenan <jkeenan@cpan.org>
Wed, 3 Oct 2018 14:52:51 +0000 (10:52 -0400)
op.c: substitute exception for warning.  Move documentation in perldiag
from W to F.  Remove tests for warnings for such statements.

Test for expected error messages for my() in false conditional.  Make
new tests more self-documenting.

For: RT # 133543

op.c
pod/perldiag.pod
t/lib/warnings/op
t/op/my.t

diff --git a/op.c b/op.c
index 03f066d..146407b 100644 (file)
--- a/op.c
+++ b/op.c
@@ -8260,9 +8260,8 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
                && o2->op_private & OPpLVAL_INTRO
                && !(o2->op_private & OPpPAD_STATE))
            {
-               Perl_ck_warner_d(aTHX_ packWARN(WARN_DEPRECATED),
-                                "Deprecated use of my() in false conditional. "
-                                "This will be a fatal error in Perl 5.30");
+        Perl_croak(aTHX_ "This use of my() in false conditional is "
+                          "no longer allowed");
            }
 
            *otherp = NULL;
index 17b96ca..59c5e79 100644 (file)
@@ -6198,6 +6198,30 @@ key traversal, but this Perl has been compiled without it.  You should
 report this warning to the relevant upstream party, or recompile perl
 with default options.
 
+=item This use of my() in false conditional is no longer allowed
+
+(F) You used a declaration similar to C<my $x if 0>.  There
+has been a long-standing bug in Perl that causes a lexical variable
+not to be cleared at scope exit when its declaration includes a false
+conditional.  Some people have exploited this bug to achieve a kind of
+static variable.  Since we intend to fix this bug, we don't want people
+relying on this behavior.  You can achieve a similar static effect by
+declaring the variable in a separate block outside the function, eg
+
+    sub f { my $x if 0; return $x++ }
+
+becomes
+
+    { my $x; sub f { return $x++ } }
+
+Beginning with perl 5.10.0, you can also use C<state> variables to have
+lexicals that are initialized only once (see L<feature>):
+
+    sub f { state $x; return $x++ }
+
+This use of C<my()> in a false conditional was deprecated beginning in
+Perl 5.10 and became a fatal error in Perl 5.30.
+
 =item times not implemented
 
 (F) Your version of the C library apparently doesn't do times().  I
index a2a1e2e..8529783 100644 (file)
@@ -1675,13 +1675,6 @@ Useless localization of match position at - line 49.
 Useless localization of vec at - line 50.
 ########
 # op.c
-my $x1 if 0;
-my @x2 if 0;
-my %x3 if 0;
-my ($x4) if 0;
-my ($x5,@x6, %x7) if 0;
-0 && my $z1;
-0 && my (%z2);
 # these shouldn't warn
 our $x if 0;
 our $x unless 0;
@@ -1690,13 +1683,6 @@ if (my $w2) { $a=1 }
 if ($a && (my $w3 = 1)) {$a = 2}
 
 EXPECT
-Deprecated use of my() in false conditional. This will be a fatal error in Perl 5.30 at - line 2.
-Deprecated use of my() in false conditional. This will be a fatal error in Perl 5.30 at - line 3.
-Deprecated use of my() in false conditional. This will be a fatal error in Perl 5.30 at - line 4.
-Deprecated use of my() in false conditional. This will be a fatal error in Perl 5.30 at - line 5.
-Deprecated use of my() in false conditional. This will be a fatal error in Perl 5.30 at - line 6.
-Deprecated use of my() in false conditional. This will be a fatal error in Perl 5.30 at - line 7.
-Deprecated use of my() in false conditional. This will be a fatal error in Perl 5.30 at - line 8.
 ########
 # op.c
 use warnings 'void';
index 3521106..5ac382c 100644 (file)
--- a/t/op/my.t
+++ b/t/op/my.t
@@ -154,5 +154,21 @@ is( $@, '', "eval of my() passes");
 eval 'my($a,$b),$x,my($c,$d)';
 pass("RT #126844");
 
+# RT # 133543
+my @false_conditionals = (
+    'my $x1 if 0;',
+    'my @x2 if 0;',
+    'my %x3 if 0;',
+    'my ($x4) if 0;',
+    'my ($x5,@x6, %x7) if 0;',
+    '0 && my $z1;',
+    '0 && my (%z2);',
+);
+for (my $i=0; $i<=$#false_conditionals; $i++) {
+    eval $false_conditionals[$i];
+    like( $@, qr/^This use of my\(\) in false conditional is no longer allowed/,
+        "RT #133543: my() in false conditional: $false_conditionals[$i]");
+}
+
 #Variable number of tests due to the way the while/for loops are tested now
 done_testing();