houseabsolute / Params-ValidationCompiler

Build an optimized subroutine parameter validator once, use it forever
https://metacpan.org/release/Params-ValidationCompiler/
Other
4 stars 5 forks source link

Optional param unexpectedly required with Perl 5.10.1 but not Perl 5.24.3 #21

Closed djerius closed 6 years ago

djerius commented 6 years ago

Params::ValidationCompiler v. 0.26

The following code (attached as validate-bug.pl.txt) should result in the sxfrm parameter being optional, but when run under Perl 5.10.1 it is treated as a required parameter:

use Params::ValidationCompiler qw[ validation_for ];
use Types::Standard -types;

my %source = (
    sxfrm => {
        type => Enum [ 'iterate', 'array', 'hash', 'error' ] | CodeRef,
        default => 'error'
    },
);
validation_for(
        params           => \%source,
        name             => insert,
        name_is_optional => 1,
      )->();

The output under Perl 5.10.1 is:

% perl validate-bug.pl
sxfrm is a required parameter for insert

Trace begun at (eval 80) line 53
main::insert at validate-bug.pl line 10

Output with Perl 5.24.3 is as expected:

% perl validate-bug.pl
%

Attached are logs of installation of the required modules on vanilla 5.10.1 (5.10.1.txt) and 5.24.3 (5.24.3.txt) and the output from the test code.

Thanks! Diab

djerius commented 6 years ago

I've run the test code against Perl versions 5.12.5, 5.14.4, 5.16.3, and 5.18.4. Perl 5.12.5 shows the unexpected behavior, the later versions do not. I've attached an installation and run log for 5.12.5 5.12.5.txt

autarch commented 6 years ago

This isn't a bug in PVC, it's an issue with how perl parses the code in question.

use strict;
use warnings;

use B::Deparse;
use Types::Standard -types;

print B::Deparse->new->coderef2text( \&foo );

sub foo {
    my %source = (
        foo => {
            type => Enum [ 'iterate', 'array', 'hash', 'error' ] | CodeRef,
            default => 'error'
        },
    );
}

Run this with 5.12.5 and I get:

{
    use warnings;
    use strict 'refs';
    my(%source) = ('foo', {'type', Enum(['iterate', 'array', 'hash', 'error'] | CodeRef, 'default', 'error')});
}

But with 5.26.1:

{
    use warnings;
    use strict;
    my(%source) = ('foo', {'type', Enum(['iterate', 'array', 'hash', 'error']) | CodeRef, 'default', 'error'});
}

Precedence is fun!

djerius commented 6 years ago

Well I'll be. That's fun. Sort of.

Thanks for looking at this!