My Favorite Warnings: shadow

Who knows what evil lurks in the hearts of men? The Shadow knows!

OK, Perl does not literally have a warning about a 1930's pulp fiction and radio serial character. But Perl 5.28 introduced shadow as a new warning category for cases where a variable is redeclared in the same scope. Previously, such warnings were under misc.

To tickle this it is sufficient to

$ perl -Mstrict -Mwarnings -Mdiagnostics -e 'my $x; my $x;'

If your Perl is at least 5.28.0, you get the diagnostic

"my" variable $x masks earlier declaration in same scope at -e line 1 (#1)
    (W shadow) A "my", "our" or "state" variable has been redeclared in the
    current scope or statement, effectively eliminating all access to the
    previous instance.  This is almost always a typographical error.  Note
    that the earlier variable will still exist until the end of the scope
    or until all closure references to it are destroyed.

Earlier Perls (back to 5.6 which is when warnings was introduced) give a similar warning, but the category is misc.

It is hard to come up with a reason why you would want to disable this warning. An extremely contrived example (do not try this at home!) would be something like

sub make_closures {
    my ( $x ) = @_;
    my $c1 = sub { $x * $_[0] };
    my $x = $x * 2;
    return ( $c1, sub { $x * $_[0] } );
}

But it would be far simpler and clearer just to call the second variable something else. If you absolutely, positively have to disable this under a range of versions of Perl, the changing category for this warning means you have to jump through some hoops. Something like this should do the trick:

my $x; # or whatever
no if "$]" >= 5.028, qw{ warnings shadow };
no if "$]" < 5.028, qw{ warnings misc };
my $x;

Note that this warning category only covers earlier declarations in the same scope. Using the same-named variable in nested scopes does not generate this diagnostic:

$ perl -Mstrict -Mwarnings -Mdiagnostics -e 'my $x; { my $x; }'

is silent.

This warning category also covers our and state variables, and lexical subroutines.


The weed of crime bears bitter fruit! Crime does not pay...The Shadow knows!

Previous entries in this series:

  1. A Belated Introduction
  2. once
  3. redundant and missing
  4. exiting
  5. uninitialized
  6. redefine
  7. Ex-Warnings
  8. deprecated
  9. experimental

3 Comments

It is hard to come up with a reason why you would want to disable this warning.

But it’s easy to see why you would might want to make it fatal without also making everything else in misc fatal – which admittedly didn’t occur to me either until I went looking for the discussion about this change.

the name is shadow! I expected it is something like mask before hahaha

Leave a comment

About Tom Wyant

user-pic I blog about Perl.