overriding types with class_type or role_type should die too
[gitmo/Moose.git] / lib / Moose / Util / TypeConstraints.pm
index a906081..6e4e2fa 100644 (file)
@@ -69,38 +69,26 @@ sub export_type_constraints_as_functions {
 }
 
 sub create_type_constraint_union {
-    my @type_constraint_names;
-
-    if ( scalar @_ == 1 && _detect_type_constraint_union( $_[0] ) ) {
-        @type_constraint_names = _parse_type_constraint_union( $_[0] );
-    }
-    else {
-        @type_constraint_names = @_;
-    }
-
-    ( scalar @type_constraint_names >= 2 )
-        || __PACKAGE__->_throw_error(
-        "You must pass in at least 2 type names to make a union");
-
-    my @type_constraints = map {
-        find_or_parse_type_constraint($_)
-            || __PACKAGE__->_throw_error(
-            "Could not locate type constraint ($_) for the union");
-    } @type_constraint_names;
-
-    return Moose::Meta::TypeConstraint::Union->new(
-        type_constraints => \@type_constraints );
+    _create_type_constraint_union(\@_);
 }
 
 sub create_named_type_constraint_union {
     my $name = shift;
+    _create_type_constraint_union($name, \@_);
+}
+
+sub _create_type_constraint_union {
+    my $name;
+    $name = shift if @_ > 1;
+    my @tcs = @{ shift() };
+
     my @type_constraint_names;
 
-    if ( scalar @_ == 1 && _detect_type_constraint_union( $_[0] ) ) {
-        @type_constraint_names = _parse_type_constraint_union( $_[0] );
+    if ( scalar @tcs == 1 && _detect_type_constraint_union( $tcs[0] ) ) {
+        @type_constraint_names = _parse_type_constraint_union( $tcs[0] );
     }
     else {
-        @type_constraint_names = @_;
+        @type_constraint_names = @tcs;
     }
 
     ( scalar @type_constraint_names >= 2 )
@@ -167,6 +155,15 @@ sub create_class_type_constraint {
 #find_type_constraint("ClassName")->check($class)
 #    || __PACKAGE__->_throw_error("Can't create a class type constraint because '$class' is not a class name");
 
+    if (my $type = $REGISTRY->get_type_constraint($class)) {
+        my $pkg_defined_in = scalar( caller(1) );
+        _confess(
+            "The type constraint '$class' has already been created in "
+          . $type->_package_defined_in
+          . " and cannot be created again in "
+          . $pkg_defined_in )
+    }
+
     my %options = (
         class => $class,
         name  => $class,
@@ -175,7 +172,9 @@ sub create_class_type_constraint {
 
     $options{name} ||= "__ANON__";
 
-    Moose::Meta::TypeConstraint::Class->new(%options);
+    my $tc = Moose::Meta::TypeConstraint::Class->new(%options);
+    $REGISTRY->add_type_constraint($tc);
+    return $tc;
 }
 
 sub create_role_type_constraint {
@@ -185,6 +184,15 @@ sub create_role_type_constraint {
 #find_type_constraint("ClassName")->check($class)
 #    || __PACKAGE__->_throw_error("Can't create a class type constraint because '$class' is not a class name");
 
+    if (my $type = $REGISTRY->get_type_constraint($role)) {
+        my $pkg_defined_in = scalar( caller(1) );
+        _confess(
+            "The type constraint '$role' has already been created in "
+          . $type->_package_defined_in
+          . " and cannot be created again in "
+          . $pkg_defined_in )
+    }
+
     my %options = (
         role => $role,
         name => $role,
@@ -193,7 +201,9 @@ sub create_role_type_constraint {
 
     $options{name} ||= "__ANON__";
 
-    Moose::Meta::TypeConstraint::Role->new(%options);
+    my $tc = Moose::Meta::TypeConstraint::Role->new(%options);
+    $REGISTRY->add_type_constraint($tc);
+    return $tc;
 }
 
 sub find_or_create_type_constraint {
@@ -335,21 +345,11 @@ sub subtype {
 }
 
 sub class_type {
-    register_type_constraint(
-        create_class_type_constraint(
-            $_[0],
-            ( defined( $_[1] ) ? $_[1] : () ),
-        )
-    );
+    create_class_type_constraint(@_);
 }
 
 sub role_type ($;$) {
-    register_type_constraint(
-        create_role_type_constraint(
-            $_[0],
-            ( defined( $_[1] ) ? $_[1] : () ),
-        )
-    );
+    create_role_type_constraint(@_);
 }
 
 sub maybe_type {
@@ -762,6 +762,10 @@ __END__
       from 'Str',
       via { 0+$_ };
 
+  class_type 'DateTimeClass', { class => 'DateTime' };
+
+  role_type 'Barks', { role => 'Some::Library::Role::Barks' };
+
   enum 'RGBColors', [qw(red green blue)];
 
   union 'StringOrArray', [qw( String Array )];
@@ -971,11 +975,29 @@ just a hashref of parameters:
 Creates a new subtype of C<Object> with the name C<$class> and the
 metaclass L<Moose::Meta::TypeConstraint::Class>.
 
+  # Create a type called 'Box' which tests for objects which ->isa('Box')
+  class_type 'Box';
+
+By default, the name of the type and the name of the class are the same, but
+you can specify both separately.
+
+  # Create a type called 'Box' which tests for objects which ->isa('ObjectLibrary::Box');
+  class_type 'Box', { class => 'ObjectLibrary::Box' };
+
 =item B<role_type ($role, ?$options)>
 
 Creates a C<Role> type constraint with the name C<$role> and the
 metaclass L<Moose::Meta::TypeConstraint::Role>.
 
+  # Create a type called 'Walks' which tests for objects which ->does('Walks')
+  role_type 'Walks';
+
+By default, the name of the type and the name of the role are the same, but
+you can specify both separately.
+
+  # Create a type called 'Walks' which tests for objects which ->does('MooseX::Role::Walks');
+  role_type 'Walks', { role => 'MooseX::Role::Walks' };
+
 =item B<maybe_type ($type)>
 
 Creates a type constraint for either C<undef> or something of the
@@ -1269,6 +1291,8 @@ form. This removes any whitespace in the string.
 
 =item B<create_type_constraint_union($pipe_separated_types | @type_constraint_names)>
 
+=item B<create_named_type_constraint_union($name, $pipe_separated_types | @type_constraint_names)>
+
 This can take a union type specification like C<'Int|ArrayRef[Int]'>,
 or a list of names. It returns a new
 L<Moose::Meta::TypeConstraint::Union> object.