MooseX::Types : subtype/coerce not found in Roles (hand_optimized_type_constraint?)

[email protected] (Ian Sillitoe)
Newsgroups perl.moose
Message-ID <[email protected]>
Hello,

I have a problem with subtype/coercions (MooseX::Types library) that I've
spent ages trying to understand, then ages trying abstract into a simple
test case but all simple cases seem to work as expected but just not in my
larger code base. I was hoping that if I put the symptoms up someone may
spot what is going on and put me out of my misery (or at least point me to
where I should continue my digging).

Please excuse any typos in the (incomplete) example code below. I have coded
up a full version of this simple scenario and I can't replicate the error
I'm getting in my real code base anyway - so this is meant purely for
illustration.

  # Types library
  package My::Types;
  use Moose;
  use MooseX::Types -declare [qw( Version DomainID )];
  use My::Version;

  subtype 'Version',
    as 'Object',
    where { $_->isa( 'My::Version' ) };

  coerce 'Version',
    from 'Str',
    via { My::Version::init_from_string( $_ ) };

  subtype 'ObjectID',
    as 'Str';

  # Role to associate versions with objects
  package My::Role::Verisoned;
  use Moose::Role;
  use My::Types qw(Version);
  has 'version' => (is => 'rw', isa => 'Version', coerce => 1);

  # Versioned Object1
  package My::Object1;
  use Moose;
  with 'My::Role::Versioned';

  # Versioned Object2
  package My::Object2;
  use Moose;
  use My::Types qw( DomainID );
  use My::Object1;
  with 'My::Role::Versioned';

  has 'domain_id' => ( is => 'rw', isa => 'DomainID' );

  sub get_object1 {
    my $self = shift;
    return My::Object1->new( version => $self->version );
  }

In this simple case, the subtype/coerce works as expected in both objects
(the type constaint of the 'version' attribute is the identical)

  $o2 = My::Object2->new( version => '3.2' );
  $o1 = $o2->get_object1;

  warn "Object1: " .
My::Object1->meta->get_attribute_map->{version}->{type_constraint}->dump;
  warn "Object2: " .
My::Object2->meta->get_attribute_map->{version}->{type_constraint}->dump;

  Object1: $VAR1 = bless( {
                    'compiled_type_constraint' => 'CODE(0xa41e310)',
                    'parent' => 'My::Version',
                    'coercion' =>
'Moose::Meta::TypeCoercion=HASH(0xa991c70)',
                    'name' => 'Version',
                    'constraint' => 'CODE(0x9eb4600)',
                    'package_defined_in' => 'My::Types'
                }, 'Moose::Meta::TypeConstraint' );

  Object2: $VAR1 = bless( {
                    'compiled_type_constraint' => 'CODE(0xa41e310)',
                    'parent' => 'My::Version',
                    'coercion' =>
'Moose::Meta::TypeCoercion=HASH(0xa991c70)',
                    'name' => 'Version',
                    'constraint' => 'CODE(0x9eb4600)',
                    'package_defined_in' => 'My::Types'
                }, 'Moose::Meta::TypeConstraint' );

However, in what seems to be a similar scenario in my live code, I get the
error that the 'version' attribute doesn't pass the type constraint when
creating an instance of Object1 inside Object2::get_object1 (it no longer
seems to be aware of the subtype/coercion in My::Types):

  Attribute (version) does not pass the type constraint because: Validation
failed for 'Version' failed with value My::Version::V3_2_0=HASH(0x1aea0930)
at .../Moose/Meta/Attribute.pm line 415

When I look at the type constraint of the 'version' attribute in these two
classes they now appear different:

  warn "Object1: " .
My::Object1->meta->get_attribute_map->{version}->{type_constraint}->dump;
  warn "Object2: " .
My::Object2->meta->get_attribute_map->{version}->{type_constraint}->dump;

  Object1: $VAR1 = bless( {
                 'compiled_type_constraint' => 'CODE(0x1ae87c00)',
                 'parent' => 'Object',
                 'hand_optimized_type_constraint' =>
$VAR1->{'compiled_type_constraint'},
                 'name' => 'Version',
                 'constraint' => 'CODE(0x1a3c4b80)',
                 'class' => 'Version'
               }, 'Moose::Meta::TypeConstraint::Class' );

  Object2: $VAR1 = bless( {
                 'compiled_type_constraint' => 'CODE(0x1a929c10)',
                 'parent' => 'My::Version',
                 'coercion' => 'Moose::Meta::TypeCoercion=HASH(0x1ae9da00)',
                 'name' => 'Version',
                 'constraint' => 'CODE(0x1a3c4b80)',
                 'package_defined_in' => 'My::Types'
               }, 'Moose::Meta::TypeConstraint' );


I hope that difference shows what I might be doing wrong or where to start
looking (parent => 'Object'? hand_optimized_type_constraint?). This change
appears to be related to which modules have been "use"d -- in my live code I
can remove this error by *taking out* the equivalent of "use My::Types" on
Object2.

Very much appreciate any help/pointers.

Cheers,

Ian


-- 
Ian Sillitoe
CATH Team -- http://cathdb.info
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.