xslate / p5-Mouse

Lightweight class builder for Perl, as a subset of Moose
https://metacpan.org/release/Mouse
Other
46 stars 32 forks source link

inconsistent coercion/validation of Bool type #16

Closed sezal closed 10 years ago

sezal commented 10 years ago

I'm trying to coerce into Bool type from pseudo-boolean class JSON::PP::Boolean which has overloaded "0+" operator and coercion doesn't even occur in case of false values (see example 1).

coerce 'Bool'
    => from 'JSON::PP::Boolean'
    => via { $_ ? 1 : 0 };

Root cause of this in constraint validation. Pseudo-false value passes Bool constraint, but Pseudo-true not (see example 2)

Btw, Moose is consistent in this case - in both cases it passes Bool constraint.

sezal commented 10 years ago

example 1

#!/usr/bin/perl
use 5.014;
use warnings;

package Boolean {

    sub new
    {
        my $self = shift;
        bless [ shift ], $self;
    }

    use overload (
       "0+"     => sub { shift->[0] ? 1 : 0 },
       fallback => 1,
    );
}

use Mouse::Util::TypeConstraints;

    class_type 'Boolean';
    coerce 'Bool'
        => from 'Boolean'
        => via { $_ ? 1 : 0 };

no Mouse::Util::TypeConstraints;

package Foo {

    use Mouse;

    has flag_true => (
        is       => 'ro',
        isa      => 'Bool',
        coerce   => 1,
    );
    has flag_false => (
        is       => 'ro',
        isa      => 'Bool',
        coerce   => 1,
    );

    no Mouse;
}

my $foo = Foo->new( flag_true => Boolean->new(1), flag_false => Boolean->new(0) );

use Data::Dumper;
warn Dumper $foo;

output

$VAR1 = bless( {
                 'flag_false' => bless( [
                                          0
                                        ], 'Boolean' ),
                 'flag_true' => 1
               }, 'Foo' );
sezal commented 10 years ago

example 2

#!/usr/bin/perl
use 5.014;
use warnings;

package Boolean {

    sub new
    {
        my $self = shift;
        bless [ shift ], $self;
    }

    use overload (
       "0+"     => sub { shift->[0] ? 1 : 0 },
       fallback => 1,
    );
}

package Foo {

    use Mouse;

    has flag => (
        is       => 'ro',
        isa      => 'Bool',
    );

    no Mouse;
}

use Data::Dumper;

my $false = Foo->new( flag => Boolean->new(0) );
warn Dumper $false;
my $true = Foo->new( flag => Boolean->new(1) );
warn Dumper $true;

output

$VAR1 = bless( {
                 'flag' => bless( [
                                    0
                                  ], 'Boolean' )
               }, 'Foo' );
Attribute (flag) does not pass the type constraint because: Validation failed for 'Bool' with value Boolean=ARRAY(0x2ff0880)...
gfx commented 10 years ago

Because Moose deals with those values as boolean, Mouse also should do so. I'll fix it in the next version.

gfx commented 10 years ago

Hmm, can I have a test to it?

sezal commented 10 years ago

do you want me to create a test under t/100_bugs/ in form of a pull request?

gfx commented 10 years ago

@sezal Yes, please.

sezal commented 10 years ago

Note, XS version is only affected.