Why does this error about strict subs only trigger under autodie?

408 Views Asked by At

Given code like this, I get no warning whatsoever.

use strict;
use warnings;
open STDERR, '>&', STDOUT;

Given this code, I get a fatal error.

use strict;
use warnings;
use autodie;
open STDERR, '>&', STDOUT;

Bareword "STDOUT" not allowed while "strict subs" in use at ./test.pl line 6. Execution of ./test.pl aborted due to compilation errors.

Why is autodie pointing at strict subs as being the source of this error -- when clearly strict was on in the first example and I had no error.

With diagnostics the error is explained like this..

Bareword "STDOUT" not allowed while "strict subs" in use at ./test.pl line 7. Execution of ./test.pl aborted due to compilation errors (#1) (F) With "strict subs" in use, a bareword is only allowed as a subroutine identifier, in curly brackets or to the left of the "=>" symbol. Perhaps you need to predeclare a subroutine?

This can all be resolved by doing

open STDERR, '>&', *STDOUT;

Then it's not a bareword, but why is the bareword special cased for open without autodie, and not with autodie? Is something else happening here?

1

There are 1 best solutions below

2
On

autodie achieves its task by exporting a sub named open that Perl uses in favour of the open operator.

$ perl -MO=Concise,-exec -e'             open(my $fh, "<", "foo")'
...
8  <@> open[t3] vK/3
...

$ perl -MO=Concise,-exec -e'use autodie; open(my $fh, "<", "foo")'
...
7  <#> gv[*open] s
8  <1> entersub vKS
...

The open operator has special parsing rules that can't be replicated by a prototype[1], so the open operator can't be accurately replicated by a sub. This accounts for the observed difference.


  1. Normally, prototype("CORE::opname") returns undefined for such operators, but prototype("CORE::open") inaccurately reports that open's parsing rules are equivalent to the *;$@ prototype.