Skip to content

Commit

Permalink
Merge pull request #103 from evalEmpire/issue/102
Browse files Browse the repository at this point in the history
Type check *after* the default is applied.  For #102
  • Loading branch information
barefootcoder committed Aug 6, 2014
2 parents cea32fc + 3568a49 commit dfd31a8
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 9 deletions.
16 changes: 8 additions & 8 deletions lib/Method/Signatures.pm
Expand Up @@ -920,7 +920,6 @@ sub inject_for_sig {
$rhs = "!$check_exists ? ($default) : do{ no warnings; my \$arg = $rhs; \$arg ~~ ($when) ? ($default) : \$arg }";
}
}

# Handle simple defaults
elsif( defined $default ) {
$rhs = "$check_exists ? ($rhs) : ($default)";
Expand All @@ -930,10 +929,6 @@ sub inject_for_sig {
push @code, qq[${class}->required_arg('$var') unless $check_exists; ];
}

if( $sig->type ) {
push @code, $self->inject_for_type_check($sig);
}

# Handle \@foo
if ( $sig->is_ref_alias or $sig->traits->{alias} ) {
require Data::Alias;
Expand All @@ -947,6 +942,10 @@ sub inject_for_sig {
push @code, "$lhs = $rhs;";
}

if( $sig->type ) {
push @code, $self->inject_for_type_check($sig);
}

# Named arg has been handled, so don't pass to error handler
push @code, "delete( $deletion_target );" if $deletion_target;

Expand All @@ -972,15 +971,16 @@ sub inject_for_type_check
my $class = ref $self || $self;
my ($sig) = @_;

my $check_exists = $sig->is_optional ? $sig->check_exists : '';
my $check_exists = $sig->is_optional && !defined $sig->default
? $sig->check_exists : '';

# This is an optimization to unroll typecheck which makes Mouse types about 40% faster.
# It only happens when type_check() has not been overridden.
if( $class->can("type_check") eq __PACKAGE__->can("type_check") ) {
my $check = sprintf q[($%s::mutc{cache}{'%s'} ||= %s->_make_constraint('%s'))->check(%s)],
__PACKAGE__, $sig->type, $class, $sig->type, $sig->passed_in;
__PACKAGE__, $sig->type, $class, $sig->type, $sig->variable;
my $error = sprintf q[%s->type_error('%s', %s, '%s') ],
$class, $sig->type, $sig->passed_in, $sig->variable_name;
$class, $sig->type, $sig->variable, $sig->variable_name;
my $code = "$error if ";
$code .= "$check_exists && " if $check_exists;
$code .= "!$check";
Expand Down
19 changes: 18 additions & 1 deletion t/defaults.t
Expand Up @@ -3,7 +3,7 @@
use strict;
use warnings;

use Test::More 'no_plan';
use Test::More;

{
package Stuff;
Expand Down Expand Up @@ -82,3 +82,20 @@ use Test::More 'no_plan';

is( Bar->code(42), 44 );
}

note "Defaults are type checked"; {
package Biff;
use Test::More;
use Method::Signatures;

func hi(
Object $place = "World"
) {
return "Hi, $place!\n";
}

ok !eval { hi() };
like $@, qr/the 'place' parameter \("World"\) is not of type Object/;
}

done_testing;
16 changes: 16 additions & 0 deletions t/when.t
Expand Up @@ -33,4 +33,20 @@ subtest "when []" => sub {
is_deeply empty_array([4,5,6]), [4,5,6];
};


subtest "Defaults are applied before type check" => sub {
package Baz;
use Test::More;
use Method::Signatures;

func hi(
Str $place //= "World"
) {
return "Hi, $place!\n";
}

is hi(), "Hi, World!\n";
is hi(undef), "Hi, World!\n";
};

done_testing;

0 comments on commit dfd31a8

Please sign in to comment.