All non-parameterized types now have inlining code
[gitmo/Moose.git] / lib / Moose / Util / TypeConstraints.pm
index 71b32d7..59d635c 100644 (file)
@@ -18,6 +18,7 @@ sub where (&);
 sub via (&);
 sub message (&);
 sub optimize_as (&);
+sub inline_as (&);
 
 ## --------------------------------------------------------
 
@@ -33,7 +34,6 @@ use Moose::Meta::TypeConstraint::DuckType;
 use Moose::Meta::TypeCoercion;
 use Moose::Meta::TypeCoercion::Union;
 use Moose::Meta::TypeConstraint::Registry;
-use Moose::Util::TypeConstraints::OptimizedConstraints;
 
 Moose::Exporter->setup_import_methods(
     as_is => [
@@ -275,7 +275,7 @@ sub type {
         Moose::Deprecated::deprecated(
             feature => 'type without sugar',
             message =>
-                'Calling type() with a simple list of parameters is deprecated'
+                'Calling type() with a simple list of parameters is deprecated. This will be an error in Moose 2.0200.'
         );
 
         return _create_type_constraint( $_[0], undef, $_[1] );
@@ -287,7 +287,7 @@ sub type {
 
     return _create_type_constraint(
         $name, undef, $p{where}, $p{message},
-        $p{optimize_as}
+        $p{optimize_as}, $p{inline_as},
     );
 }
 
@@ -300,7 +300,7 @@ sub subtype {
         Moose::Deprecated::deprecated(
             feature => 'subtype without sugar',
             message =>
-                'Calling subtype() with a simple list of parameters is deprecated'
+                'Calling subtype() with a simple list of parameters is deprecated. This will be an error in Moose 2.0200.'
         );
 
         return _create_type_constraint( undef, @_ );
@@ -313,7 +313,7 @@ sub subtype {
         Moose::Deprecated::deprecated(
             feature => 'subtype without sugar',
             message =>
-                'Calling subtype() with a simple list of parameters is deprecated'
+                'Calling subtype() with a simple list of parameters is deprecated. This will be an error in Moose 2.0200.'
         );
 
         return _create_type_constraint( undef, @_ );
@@ -324,7 +324,7 @@ sub subtype {
         Moose::Deprecated::deprecated(
             feature => 'subtype without sugar',
             message =>
-                'Calling subtype() with a simple list of parameters is deprecated'
+                'Calling subtype() with a simple list of parameters is deprecated. This will be an error in Moose 2.0200.'
         );
 
         return _create_type_constraint(@_);
@@ -350,7 +350,7 @@ sub subtype {
 
     return _create_type_constraint(
         $name, $p{as}, $p{where}, $p{message},
-        $p{optimize_as}
+        $p{optimize_as}, $p{inline_as},
     );
 }
 
@@ -414,12 +414,13 @@ sub coerce {
 #
 # subtype( 'Foo', as( 'Str', where { ... } ) );
 #
-# If as() returns all it's extra arguments, this just works, and
+# If as() returns all its extra arguments, this just works, and
 # preserves backwards compatibility.
 sub as { { as => shift }, @_ }
 sub where (&)       { { where       => $_[0] } }
 sub message (&)     { { message     => $_[0] } }
 sub optimize_as (&) { { optimize_as => $_[0] } }
+sub inline_as (&)   { { inline_as   => $_[0] } }
 
 sub from    {@_}
 sub via (&) { $_[0] }
@@ -511,6 +512,7 @@ sub _create_type_constraint ($$$;$$) {
     my $check     = shift;
     my $message   = shift;
     my $optimized = shift;
+    my $inlined   = shift;
 
     my $pkg_defined_in = scalar( caller(1) );
 
@@ -537,6 +539,7 @@ sub _create_type_constraint ($$$;$$) {
         ( $check     ? ( constraint => $check )     : () ),
         ( $message   ? ( message    => $message )   : () ),
         ( $optimized ? ( optimized  => $optimized ) : () ),
+        ( $inlined   ? ( inlined    => $inlined )   : () ),
     );
 
     my $constraint;
@@ -678,8 +681,9 @@ sub _install_type_coercions ($$) {
 # define some basic built-in types
 ## --------------------------------------------------------
 
-# By making these classes immutable before creating all the types we
-# below, we avoid repeatedly calling the slow MOP-based accessors.
+# By making these classes immutable before creating all the types in
+# Moose::Util::TypeConstraints::Builtin , we avoid repeatedly calling the slow
+# MOP-based accessors.
 $_->make_immutable(
     inline_constructor => 1,
     constructor_name   => "_new",
@@ -700,147 +704,8 @@ $_->make_immutable(
     Moose::Meta::TypeConstraint::Registry
 );
 
-type 'Any'  => where {1};    # meta-type including all
-subtype 'Item' => as 'Any';  # base-type
-
-subtype 'Undef'   => as 'Item' => where { !defined($_) };
-subtype 'Defined' => as 'Item' => where { defined($_) };
-
-subtype 'Bool' => as 'Item' =>
-    where { !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq '0' };
-
-subtype 'Value' => as 'Defined' => where { !ref($_) } =>
-    optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Value;
-
-subtype 'Ref' => as 'Defined' => where { ref($_) } =>
-    optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Ref;
-
-subtype 'Str' => as 'Value' => where { ref(\$_) eq 'SCALAR' } =>
-    optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Str;
-
-subtype 'Num' => as 'Str' =>
-    where { Scalar::Util::looks_like_number($_) } =>
-    optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Num;
-
-subtype 'Int' => as 'Num' => where { "$_" =~ /^-?[0-9]+$/ } =>
-    optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Int;
-
-subtype 'CodeRef' => as 'Ref' => where { ref($_) eq 'CODE' } =>
-    optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::CodeRef;
-subtype 'RegexpRef' => as 'Ref' => where { ref($_) eq 'Regexp' } =>
-    optimize_as
-    \&Moose::Util::TypeConstraints::OptimizedConstraints::RegexpRef;
-subtype 'GlobRef' => as 'Ref' => where { ref($_) eq 'GLOB' } =>
-    optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::GlobRef;
-
-# NOTE:
-# scalar filehandles are GLOB refs,
-# but a GLOB ref is not always a filehandle
-subtype 'FileHandle' => as 'GlobRef' => where {
-    Scalar::Util::openhandle($_) || ( blessed($_) && $_->isa("IO::Handle") );
-} => optimize_as
-    \&Moose::Util::TypeConstraints::OptimizedConstraints::FileHandle;
-
-# NOTE:
-# blessed(qr/.../) returns true,.. how odd
-subtype 'Object' => as 'Ref' =>
-    where { blessed($_) && blessed($_) ne 'Regexp' } =>
-    optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Object;
-
-# This type is deprecated.
-subtype 'Role' => as 'Object' => where { $_->can('does') } =>
-    optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Role;
-
-my $_class_name_checker = sub { };
-
-subtype 'ClassName' => as 'Str' =>
-    where { Class::MOP::is_class_loaded($_) } => optimize_as
-    \&Moose::Util::TypeConstraints::OptimizedConstraints::ClassName;
-
-subtype 'RoleName' => as 'ClassName' => where {
-    (Class::MOP::class_of($_) || return)->isa('Moose::Meta::Role');
-} => optimize_as
-    \&Moose::Util::TypeConstraints::OptimizedConstraints::RoleName;
-
-## --------------------------------------------------------
-# parameterizable types ...
-
-$REGISTRY->add_type_constraint(
-    Moose::Meta::TypeConstraint::Parameterizable->new(
-        name               => 'ScalarRef',
-        package_defined_in => __PACKAGE__,
-        parent             => find_type_constraint('Ref'),
-        constraint         => sub { ref($_) eq 'SCALAR' || ref($_) eq 'REF' },
-        optimized =>
-            \&Moose::Util::TypeConstraints::OptimizedConstraints::ScalarRef,
-        constraint_generator => sub {
-            my $type_parameter = shift;
-            my $check          = $type_parameter->_compiled_type_constraint;
-            return sub {
-                return $check->(${ $_ });
-            };
-        }
-    )
-);
-
-$REGISTRY->add_type_constraint(
-    Moose::Meta::TypeConstraint::Parameterizable->new(
-        name               => 'ArrayRef',
-        package_defined_in => __PACKAGE__,
-        parent             => find_type_constraint('Ref'),
-        constraint         => sub { ref($_) eq 'ARRAY' },
-        optimized =>
-            \&Moose::Util::TypeConstraints::OptimizedConstraints::ArrayRef,
-        constraint_generator => sub {
-            my $type_parameter = shift;
-            my $check          = $type_parameter->_compiled_type_constraint;
-            return sub {
-                foreach my $x (@$_) {
-                    ( $check->($x) ) || return;
-                }
-                1;
-                }
-        }
-    )
-);
-
-$REGISTRY->add_type_constraint(
-    Moose::Meta::TypeConstraint::Parameterizable->new(
-        name               => 'HashRef',
-        package_defined_in => __PACKAGE__,
-        parent             => find_type_constraint('Ref'),
-        constraint         => sub { ref($_) eq 'HASH' },
-        optimized =>
-            \&Moose::Util::TypeConstraints::OptimizedConstraints::HashRef,
-        constraint_generator => sub {
-            my $type_parameter = shift;
-            my $check          = $type_parameter->_compiled_type_constraint;
-            return sub {
-                foreach my $x ( values %$_ ) {
-                    ( $check->($x) ) || return;
-                }
-                1;
-                }
-        }
-    )
-);
-
-$REGISTRY->add_type_constraint(
-    Moose::Meta::TypeConstraint::Parameterizable->new(
-        name                 => 'Maybe',
-        package_defined_in   => __PACKAGE__,
-        parent               => find_type_constraint('Item'),
-        constraint           => sub {1},
-        constraint_generator => sub {
-            my $type_parameter = shift;
-            my $check          = $type_parameter->_compiled_type_constraint;
-            return sub {
-                return 1 if not( defined($_) ) || $check->($_);
-                return;
-                }
-        }
-    )
-);
+require Moose::Util::TypeConstraints::Builtins;
+Moose::Util::TypeConstraints::Builtins::define_builtins($REGISTRY);
 
 my @PARAMETERIZABLE_TYPES
     = map { $REGISTRY->get_type_constraint($_) } qw[ScalarRef ArrayRef HashRef Maybe];
@@ -885,20 +750,20 @@ __END__
 
   use Moose::Util::TypeConstraints;
 
-  subtype 'Natural'
-      => as 'Int'
-      => where { $_ > 0 };
+  subtype 'Natural',
+      as 'Int',
+      where { $_ > 0 };
 
-  subtype 'NaturalLessThanTen'
-      => as 'Natural'
-      => where { $_ < 10 }
-      => message { "This number ($_) is not less than ten!" };
+  subtype 'NaturalLessThanTen',
+      as 'Natural',
+      where { $_ < 10 },
+      message { "This number ($_) is not less than ten!" };
 
-  coerce 'Num'
-      => from 'Str'
-        => via { 0+$_ };
+  coerce 'Num',
+      from 'Str',
+      via { 0+$_ };
 
-  enum 'RGBColors' => qw(red green blue);
+  enum 'RGBColors', [qw(red green blue)];
 
   no Moose::Util::TypeConstraints;
 
@@ -940,7 +805,7 @@ this, as well as future proof your subtypes from classes which have
 yet to have been created, is to quote the type name:
 
   use DateTime;
-  subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') };
+  subtype 'DateTime', as 'Object', where { $_->isa('DateTime') };
 
 =head2 Default Type Constraints
 
@@ -1011,7 +876,7 @@ I<My::Graphics::Types::Color> instead.
 
 This module can play nicely with other constraint modules with some
 slight tweaking. The C<where> clause in types is expected to be a
-C<CODE> reference which checks it's first argument and returns a
+C<CODE> reference which checks its first argument and returns a
 boolean. Since most constraint modules work in a similar way, it
 should be simple to adapt them to work with Moose.
 
@@ -1019,21 +884,21 @@ For instance, this is how you could use it with
 L<Declare::Constraints::Simple> to declare a completely new type.
 
   type 'HashOfArrayOfObjects',
-      {
-      where => IsHashRef(
-          -keys   => HasLength,
-          -values => IsArrayRef(IsObject)
-      )
-  };
-
-For more examples see the F<t/200_examples/004_example_w_DCS.t> test
+      where {
+          IsHashRef(
+              -keys   => HasLength,
+              -values => IsArrayRef(IsObject)
+          )->(@_);
+      };
+
+For more examples see the F<t/examples/example_w_DCS.t> test
 file.
 
-Here is an example of using L<Test::Deep> and it's non-test
+Here is an example of using L<Test::Deep> and its non-test
 related C<eq_deeply> function.
 
-  type 'ArrayOfHashOfBarsAndRandomNumbers'
-      => where {
+  type 'ArrayOfHashOfBarsAndRandomNumbers',
+      where {
           eq_deeply($_,
               array_each(subhashof({
                   bar           => isa('Bar'),
@@ -1042,7 +907,23 @@ related C<eq_deeply> function.
         };
 
 For a complete example see the
-F<t/200_examples/005_example_w_TestDeep.t> test file.
+F<t/examples/example_w_TestDeep.t> test file.
+
+=head2 Error messages
+
+Type constraints can also specify custom error messages, for when they fail to
+validate. This is provided as just another coderef, which receives the invalid
+value in C<$_>, as in:
+
+  subtype 'PositiveInt',
+       as 'Int',
+       where { $_ > 0 },
+       message { "$_ is not a positive integer!" };
+
+If no message is specified, a default message will be used, which indicates
+which type constraint was being used and what value failed. If
+L<Devel::PartialDump> (version 0.14 or higher) is installed, it will be used to
+display the invalid value, otherwise it will just be printed as is.
 
 =head1 FUNCTIONS
 
@@ -1056,7 +937,7 @@ See the L</SYNOPSIS> for an example of how to use these.
 
 =over 4
 
-=item B<< subtype 'Name' => as 'Parent' => where { } ... >>
+=item B<< subtype 'Name', as 'Parent', where { } ... >>
 
 This creates a named subtype.
 
@@ -1072,7 +953,7 @@ name and a hashref of parameters:
 The valid hashref keys are C<as> (the parent), C<where>, C<message>,
 and C<optimize_as>.
 
-=item B<< subtype as 'Parent' => where { } ... >>
+=item B<< subtype as 'Parent', where { } ... >>
 
 This creates an unnamed subtype and will return the type
 constraint meta-object, which will be an instance of
@@ -1174,7 +1055,7 @@ B<NOTE:> You should only use this if you know what you are doing.
 All the built in types use this, so your subtypes (assuming they
 are shallow) will not likely need to use this.
 
-=item B<< type 'Name' => where { } ... >>
+=item B<< type 'Name', where { } ... >>
 
 This creates a base type, which has no parent.
 
@@ -1273,16 +1154,16 @@ See the L</SYNOPSIS> for an example of how to use these.
 
 =over 4
 
-=item B<< coerce 'Name' => from 'OtherName' => via { ... }  >>
+=item B<< coerce 'Name', from 'OtherName', via { ... }  >>
 
 This defines a coercion from one type to another. The C<Name> argument
 is the type you are coercing I<to>.
 
 To define multiple coercions, supply more sets of from/via pairs:
 
-  coerce 'Name' =>
-    from 'OtherName' => via { ... },
-    from 'ThirdName' => via { ... };
+  coerce 'Name',
+    from 'OtherName', via { ... },
+    from 'ThirdName', via { ... };
 
 =item B<from 'OtherName'>
 
@@ -1387,7 +1268,7 @@ global registry.
 =item B<find_or_create_does_type_constraint($type_name)>
 
 These functions will first call C<find_or_parse_type_constraint>. If
-that function does not return a type, a new anonymous type object will
+that function does not return a type, a new type object will
 be created.
 
 The C<isa> variant will use C<create_class_type_constraint> and the