Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Perl-Critic CPAN distribution.

Report information
The Basics
Id: 79138
Status: open
Priority: 0/
Queue: Perl-Critic

People
Owner: Nobody in particular
Requestors: jffry [...] posteo.net
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: RequireArgUnpacking confused by @_ in finally{}
Date: Wed, 22 Aug 2012 18:48:43 +0200
To: bug-Perl-Critic [...] rt.cpan.org
From: Jeffrey Ratcliffe <jeffrey.ratcliffe [...] gmail.com>
For the code below, P::C complains Always unpack @_ first at line 7, column 1. See page 178 of PBP. (Severity: 4) If you comment out the print and unless in finally{}, then the error disappears. #!/usr/bin/perl use strict; use warnings; use Try::Tiny; sub my_method { my ( $self ) = @_; try { sub_which_could_fail(); } catch { deal_with_error(); } finally { print 'No error' unless (@_); }; return; }
Subject: Re: [rt.cpan.org #79138] RequireArgUnpacking confused by @_ in finally{}
Date: Wed, 22 Aug 2012 13:43:57 -0700
To: bug-Perl-Critic [...] rt.cpan.org
From: Jeffrey Thalhammer <jeff [...] imaginative-software.com>
Yup, that's a bug. Thanks for bringing it to our attention.
Coupla thoughts: First, it seems to me that the use of finally() is not directly related to what perlcritic is doing. My evidence: the script #!/usr/bin/perl use strict; use warnings; use Try::Tiny; sub my_method { my ( $self ) = @_; # try { # sub_which_could_fail(); # } # catch { # deal_with_error(); # } # finally { print 'No error' unless (@_); # }; return; } (with everything commented out _but_ the offending line, and in particular the whole try/catch/finally thing) produces exactly the same error. Second, the line number reported is, strictly speaking, wrong; it ought to be line 16, since the @_ in the finally() block (in the original example) has nothing to do with the @_ in the subroutine at large. I have not looked at programming this change, though my knee-jerk is that I'm not smart enough to do it -- at least, not without building into Perl::Critic an intimate knowledge of how Try::Tiny works. I may be wrong, though, since setting short_subroutine_statements = 3 suppresses the error. Third, it appears to me that Damien does not address uses of @_ to discover the number of arguments. It also seems to me that this is what the ticket is really about. The policy actually has some code to allow checking the number of arguments, though at this point the only things allowed are '@_ == $something', '$something == @_', '@_ != $something', and '$something != @_'. Maybe it should have more?
Based on my third thought above (that the real problem is that the logic to allow testing the size of the argument list is not comprehensive enough), I have committed some changes that may help. I have added the other comparison operators (the original only covered '$something == @_', '@_ == $something', $something != @_, and '@_ != $something'), plus Boolean operators, plus logic to handle suffix conditionals. The .run file has an added test, though the test does not cover the Cartesian product of all the possibilities. The commit is SVN revision 4151.
Subject: Re: [rt.cpan.org #79138] RequireArgUnpacking confused by @_ in finally{}
Date: Thu, 23 Aug 2012 21:49:25 -0700
To: bug-Perl-Critic [...] rt.cpan.org
From: Jeffrey Thalhammer <jeff [...] imaginative-software.com>
On Aug 23, 2012, at 8:27 PM, Tom Wyant via RT wrote: Show quoted text
> Based on my third thought above (that the real problem is that the logic > to allow testing the size of the argument list is not comprehensive > enough), I have committed some changes that may help.
I understood the problem differently. The argument to finally is a code ref that is given some arguments when invoked. Basically, it is a subroutine declaration within a subroutine declaration. But PPI doesn't see it that way, because it doesn't see the 'sub' keyword. So the policy sees the @_ inside the finally block as the arguments that were passed to the enclosing named subroutine. But they aren't. So strictly speaking, the sample code is fully compliant. Within the finally "subroutine", @_ is handled immediately. Does that make sense? -Jeff
On Fri Aug 24 00:49:38 2012, jeff@imaginative-software.com wrote: Show quoted text
> > On Aug 23, 2012, at 8:27 PM, Tom Wyant via RT wrote: >
> > Based on my third thought above (that the real problem is that the
> logic
> > to allow testing the size of the argument list is not comprehensive > > enough), I have committed some changes that may help.
> > I understood the problem differently. The argument to finally is a > code ref that is given some arguments when invoked. Basically, it > is a subroutine declaration within a subroutine declaration. But > PPI doesn't see it that way, because it doesn't see the 'sub' > keyword. So the policy sees the @_ inside the finally block as the > arguments that were passed to the enclosing named subroutine. But > they aren't. > > So strictly speaking, the sample code is fully compliant. Within the > finally "subroutine", @_ is handled immediately. Does that make > sense?
You are right that the @_ in the finally() block is not the same as the @_ at the top of the sub. And Perl::Critic seems to be dimly aware of this, as shown by the fact that I have to run -noprof to duplicate the error, apparently because my .perlcriticrc has 'short_subroutine_statements = 3'. But when I run Perl::Critic 1.18 against sub my_method { print 'No error' unless (@_); return; } which I believe to be structurally equivalent to the original poster's code, I get $ perlcritic --single ArgUnpacking -noprof fubar.pl Always unpack @_ first at line 1, column 1. See page 178 of PBP. (Severity: 4) Do you get something different? Or is there something wrong with my example? I think the error is because 'unless( @_ )' is neither an assignment nor a shift. I suspect that the error could also (in this specific case) be suppressed by 'allow_delegation_to = unless', but I have not investigated.