Skip to content

Valid coercions reported as invalid if unrelated data fails #81

@Ovid

Description

@Ovid

I'm assuming I'm doing something horribly wrong, but here's a tiny type library (I've tried to pare it down to a minimal test case). Note that the YAMLBool type coerces true and false to 1 and 0, respectively:

package MyTypes {
    use Type::Library -base, -declare => qw(
      YAMLBool
    );
    use Type::Params 'compile';
    use Type::Utils -all;
    use Types::Standard qw(Bool Enum Dict Optional HashRef);

    our @EXPORT_OK = 'compile';

    BEGIN {
        extends qw(
          Types::Standard
          Types::Common::Numeric
          Types::Common::String
        );
    }
    declare '_TrueFalse', as Enum [qw/true false/];
    declare 'YAMLBool',   as Bool;
    coerce 'YAMLBool',
      from '_TrueFalse', via { 'true' eq $_ ? 1 : 0 };
}

1;

And here's a program that succeeds:

use 5.26.0;
use warnings;
use lib '.';
use MyTypes qw/Dict YAMLBool Optional HashRef compile/;

my $check = compile(
    Dict [
        maybe_true    => YAMLBool,
        not_a_hashref => Optional [HashRef],
    ]
);

my $minimal = {
    maybe_true    => 'true',
    not_a_hashref => {},
};

$check->($minimal);

But as soon as I change the not_a_hashref value to a string, I get the following error:

Reference {"maybe_true" => "true","not_a_hashref" => "asdf"} did not pass type constraint "Dict[maybe_true=>YAMLBool,not_a_hashref=>Optional[HashRef]]" (in $_[0]) at fail.pl line 18
    Reference {"maybe_true" => "true","not_a_hashref" => "asdf"} did not pass type constraint "Dict[maybe_true=>YAMLBool,not_a_hashref=>Optional[HashRef]]" (in $_[0])
    "Dict[maybe_true=>YAMLBool,not_a_hashref=>Optional[HashRef]]" constrains value at key "maybe_true" of hash with "YAMLBool"
    "YAMLBool" is a subtype of "Bool"
    Value "true" did not pass type constraint "Bool" (in $_[0]->{"maybe_true"})
    "Bool" is defined as: (!ref $_ and (!defined $_ or $_ eq q() or $_ eq '0' or $_ eq '1'))

So we see the coercion is valid. However, as soon as I change something other than the coerced value to an invalid state, the coercion doesn't happen and this otherwise valid value is reported as being the source of the problem. The actual type I compiled was about 40 lines long, so this was rather hard to chase down.

  • Types::Standard version 1.012001
  • Perl 5.26.2

I've also had this happen on Linux boxes with newer Perls and older versions of Types::Standard (1.010006), so it appears that I can reliably produce it.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions