A horrible hack to make generating a coercion for a type union lazy
Dave Rolsky [Fri, 27 Aug 2010 21:15:48 +0000 (16:15 -0500)]
This fixes a bug that was triggered by recursive type constraints in MX::Types.

lib/Moose/Meta/TypeConstraint/Union.pm
xt/author/pod_coverage.t

index 41654f6..02d55e0 100644 (file)
@@ -7,6 +7,7 @@ use metaclass;
 
 use Moose::Meta::TypeCoercion::Union;
 
+use List::MoreUtils qw(any);
 use List::Util qw(first);
 
 our $VERSION   = '1.10';
@@ -33,13 +34,29 @@ sub new {
 
     $self->_set_constraint(sub { $self->check($_[0]) });
 
-    if ( grep { $_->has_coercion } @{ $self->type_constraints } ) {
-        $self->coercion(
-            Moose::Meta::TypeCoercion::Union->new( type_constraint => $self )
-        );
+    return $self;
+}
+
+# XXX - this is a rather gross implementation of laziness for the benefit of
+# MX::Types. If we try to call ->has_coercion on the objects during object
+# construction, this does not work when defining a recursive constraint with
+# MX::Types.
+sub coercion {
+    my $self = shift;
+
+    return $self->{coercion} if exists $self->{coercion};
+
+    if ( any { $_->has_coercion } @{ $self->type_constraints } ) {
+        return $self->{coercion} = Moose::Meta::TypeCoercion::Union->new(
+            type_constraint => $self );
+    }
+    else {
+        return $self->{coercion} = undef;
     }
+}
 
-    return $self;
+sub has_coercion {
+    return defined $_[0]->coercion;
 }
 
 sub _actually_compile_type_constraint {
index cda0317..93232d8 100644 (file)
@@ -92,10 +92,11 @@ my %trustme = (
         [qw( constraint equals get_message )],
     'Moose::Meta::TypeConstraint::Parameterizable' => ['.+'],
     'Moose::Meta::TypeConstraint::Parameterized'   => ['.+'],
-    'Moose::Meta::TypeConstraint::Role'  => [qw( equals is_a_type_of )],
-    'Moose::Meta::TypeConstraint::Union' => ['compile_type_constraint'],
-    'Moose::Util'                        => ['add_method_modifier'],
-    'Moose::Util::MetaRole'              => ['apply_metaclass_roles'],
+    'Moose::Meta::TypeConstraint::Role' => [qw( equals is_a_type_of )],
+    'Moose::Meta::TypeConstraint::Union' =>
+        [qw( compile_type_constraint coercion has_coercion)],
+    'Moose::Util'                  => ['add_method_modifier'],
+    'Moose::Util::MetaRole'        => ['apply_metaclass_roles'],
     'Moose::Util::TypeConstraints' => ['find_or_create_type_constraint'],
 );