fix ClassName constraint to use symbol table
[gitmo/Moose.git] / lib / Moose / Util / TypeConstraints.pm
1
2 package Moose::Util::TypeConstraints;
3
4 use strict;
5 use warnings;
6
7 use Carp         'confess';
8 use Scalar::Util 'blessed', 'reftype';
9 use B            'svref_2object';
10 use Sub::Exporter;
11
12 our $VERSION   = '0.15';
13 our $AUTHORITY = 'cpan:STEVAN';
14
15 ## --------------------------------------------------------
16 # Prototyped subs must be predeclared because we have a
17 # circular dependency with Moose::Meta::Attribute et. al.
18 # so in case of us being use'd first the predeclaration
19 # ensures the prototypes are in scope when consumers are
20 # compiled.
21
22 # creation and location
23 sub find_type_constraint                 ($);
24 sub find_or_create_type_constraint       ($;$);
25 sub create_type_constraint_union         (@);
26 sub create_parameterized_type_constraint ($);
27
28 # dah sugah!
29 sub type        ($$;$$);
30 sub subtype     ($$;$$$);
31 sub coerce      ($@);
32 sub as          ($);
33 sub from        ($);
34 sub where       (&);
35 sub via         (&);
36 sub message     (&);
37 sub optimize_as (&);
38 sub enum        ($;@);
39
40 ## private stuff ...
41 sub _create_type_constraint ($$$;$$);
42 sub _install_type_coercions ($$);
43
44 ## --------------------------------------------------------
45
46 use Moose::Meta::TypeConstraint;
47 use Moose::Meta::TypeConstraint::Union;
48 use Moose::Meta::TypeConstraint::Parameterized;
49 use Moose::Meta::TypeCoercion;
50 use Moose::Meta::TypeCoercion::Union;
51 use Moose::Meta::TypeConstraint::Registry;
52
53 my @exports = qw/
54     type subtype as where message optimize_as
55     coerce from via
56     enum
57     find_type_constraint
58 /;
59
60 Sub::Exporter::setup_exporter({
61     exports => \@exports,
62     groups  => { default => [':all'] }
63 });
64
65 sub unimport {
66     no strict 'refs';
67     my $class = caller();
68     # loop through the exports ...
69     foreach my $name (@exports) {
70         # if we find one ...
71         if (defined &{$class . '::' . $name}) {
72             my $keyword = \&{$class . '::' . $name};
73
74             # make sure it is from Moose
75             my $pkg_name = eval { svref_2object($keyword)->GV->STASH->NAME };
76             next if $@;
77             next if $pkg_name ne 'Moose::Util::TypeConstraints';
78
79             # and if it is from Moose then undef the slot
80             delete ${$class . '::'}{$name};
81         }
82     }
83 }
84
85 ## --------------------------------------------------------
86 ## type registry and some useful functions for it
87 ## --------------------------------------------------------
88
89 my $REGISTRY = Moose::Meta::TypeConstraint::Registry->new;
90
91 sub get_type_constraint_registry         { $REGISTRY }
92 sub list_all_type_constraints            { keys %{$REGISTRY->type_constraints} }
93 sub export_type_constraints_as_functions {
94     my $pkg = caller();
95     no strict 'refs';
96         foreach my $constraint (keys %{$REGISTRY->type_constraints}) {
97                 *{"${pkg}::${constraint}"} = $REGISTRY->get_type_constraint($constraint)
98                                                       ->_compiled_type_constraint;
99         }
100 }
101
102 sub create_type_constraint_union (@) {
103     my @type_constraint_names;
104
105     if (scalar @_ == 1 && _detect_type_constraint_union($_[0])) {
106         @type_constraint_names = _parse_type_constraint_union($_[0]);
107     }
108     else {
109         @type_constraint_names = @_;
110     }
111
112     (scalar @type_constraint_names >= 2)
113         || confess "You must pass in at least 2 type names to make a union";
114
115     ($REGISTRY->has_type_constraint($_))
116         || confess "Could not locate type constraint ($_) for the union"
117             foreach @type_constraint_names;
118
119     return Moose::Meta::TypeConstraint::Union->new(
120         type_constraints => [
121             map {
122                 $REGISTRY->get_type_constraint($_)
123             } @type_constraint_names
124         ],
125     );
126 }
127
128 sub create_parameterized_type_constraint ($) {
129     my $type_constraint_name = shift;
130
131     my ($base_type, $type_parameter) = _parse_parameterized_type_constraint($type_constraint_name);
132
133     (defined $base_type && defined $type_parameter)
134         || confess "Could not parse type name ($type_constraint_name) correctly";
135
136     ($REGISTRY->has_type_constraint($base_type))
137         || confess "Could not locate the base type ($base_type)";
138
139     return Moose::Meta::TypeConstraint::Parameterized->new(
140         name           => $type_constraint_name,
141         parent         => $REGISTRY->get_type_constraint($base_type),
142         type_parameter => find_or_create_type_constraint(
143             $type_parameter => {
144                 parent     => $REGISTRY->get_type_constraint('Object'),
145                 constraint => sub { $_[0]->isa($type_parameter) }
146             }
147         ),
148     );
149 }
150
151 sub find_or_create_type_constraint ($;$) {
152     my ($type_constraint_name, $options_for_anon_type) = @_;
153
154     return $REGISTRY->get_type_constraint($type_constraint_name)
155         if $REGISTRY->has_type_constraint($type_constraint_name);
156
157     my $constraint;
158
159     if (_detect_type_constraint_union($type_constraint_name)) {
160         $constraint = create_type_constraint_union($type_constraint_name);
161     }
162     elsif (_detect_parameterized_type_constraint($type_constraint_name)) {
163         $constraint = create_parameterized_type_constraint($type_constraint_name);
164     }
165     else {
166         # NOTE:
167         # otherwise assume that we should create
168         # an ANON type with the $options_for_anon_type
169         # options which can be passed in. It should
170         # be noted that these don't get registered
171         # so we need to return it.
172         # - SL
173         return Moose::Meta::TypeConstraint->new(
174             name => '__ANON__',
175             %{$options_for_anon_type}
176         );
177     }
178
179     $REGISTRY->add_type_constraint($constraint);
180     return $constraint;
181 }
182
183 ## --------------------------------------------------------
184 ## exported functions ...
185 ## --------------------------------------------------------
186
187 sub find_type_constraint ($) { $REGISTRY->get_type_constraint(@_) }
188
189 # type constructors
190
191 sub type ($$;$$) {
192     splice(@_, 1, 0, undef);
193         goto &_create_type_constraint;
194 }
195
196 sub subtype ($$;$$$) {
197     # NOTE:
198     # this adds an undef for the name
199     # if this is an anon-subtype:
200     #   subtype(Num => where { $_ % 2 == 0 }) # anon 'even' subtype
201     # but if the last arg is not a code
202     # ref then it is a subtype alias:
203     #   subtype(MyNumbers => as Num); # now MyNumbers is the same as Num
204     # ... yeah I know it's ugly code
205     # - SL
206         unshift @_ => undef if scalar @_ <= 2 && (reftype($_[1]) || '') eq 'CODE';
207         goto &_create_type_constraint;
208 }
209
210 sub coerce ($@) {
211     my ($type_name, @coercion_map) = @_;
212     _install_type_coercions($type_name, \@coercion_map);
213 }
214
215 sub as      ($) { $_[0] }
216 sub from    ($) { $_[0] }
217 sub where   (&) { $_[0] }
218 sub via     (&) { $_[0] }
219
220 sub message     (&) { +{ message   => $_[0] } }
221 sub optimize_as (&) { +{ optimized => $_[0] } }
222
223 sub enum ($;@) {
224     my ($type_name, @values) = @_;
225     (scalar @values >= 2)
226         || confess "You must have at least two values to enumerate through";
227     my %valid = map { $_ => 1 } @values;
228         _create_type_constraint(
229             $type_name,
230             'Str',
231             sub { $valid{$_} }
232         );
233 }
234
235 ## --------------------------------------------------------
236 ## desugaring functions ...
237 ## --------------------------------------------------------
238
239 sub _create_type_constraint ($$$;$$) {
240     my $name   = shift;
241     my $parent = shift;
242     my $check  = shift || sub { 1 };
243
244     my ($message, $optimized);
245     for (@_) {
246         $message   = $_->{message}   if exists $_->{message};
247         $optimized = $_->{optimized} if exists $_->{optimized};
248     }
249
250     my $pkg_defined_in = scalar(caller(0));
251
252     if (defined $name) {
253         my $type = $REGISTRY->get_type_constraint($name);
254
255         ($type->_package_defined_in eq $pkg_defined_in)
256             || confess ("The type constraint '$name' has already been created in "
257                        . $type->_package_defined_in . " and cannot be created again in "
258                        . $pkg_defined_in)
259                  if defined $type;
260     }
261
262     $parent = $REGISTRY->get_type_constraint($parent) if defined $parent;
263
264     my $constraint = Moose::Meta::TypeConstraint->new(
265         name               => $name || '__ANON__',
266         package_defined_in => $pkg_defined_in,
267
268         ($parent    ? (parent     => $parent )   : ()),
269         ($check     ? (constraint => $check)     : ()),
270         ($message   ? (message    => $message)   : ()),
271         ($optimized ? (optimized  => $optimized) : ()),
272     );
273
274     $REGISTRY->add_type_constraint($constraint)
275         if defined $name;
276
277     return $constraint;
278 }
279
280 sub _install_type_coercions ($$) {
281     my ($type_name, $coercion_map) = @_;
282     my $type = $REGISTRY->get_type_constraint($type_name);
283     (!$type->has_coercion)
284         || confess "The type coercion for '$type_name' has already been registered";
285     my $type_coercion = Moose::Meta::TypeCoercion->new(
286         type_coercion_map => $coercion_map,
287         type_constraint   => $type
288     );
289     $type->coercion($type_coercion);
290 }
291
292 ## --------------------------------------------------------
293 ## type notation parsing ...
294 ## --------------------------------------------------------
295
296 {
297     # All I have to say is mugwump++ cause I know
298     # do not even have enough regexp-fu to be able
299     # to have written this (I can only barely
300     # understand it as it is)
301     # - SL
302
303     use re "eval";
304
305     my $valid_chars = qr{[\w:]};
306     my $type_atom   = qr{ $valid_chars+ };
307
308     my $type                = qr{  $valid_chars+  (?: \[  (??{$any})  \] )? }x;
309     my $type_capture_parts  = qr{ ($valid_chars+) (?: \[ ((??{$any})) \] )? }x;
310     my $type_with_parameter = qr{  $valid_chars+      \[  (??{$any})  \]    }x;
311
312     my $op_union = qr{ \s* \| \s* }x;
313     my $union    = qr{ $type (?: $op_union $type )+ }x;
314
315     our $any = qr{ $type | $union }x;
316
317     sub _parse_parameterized_type_constraint {
318         $_[0] =~ m{ $type_capture_parts }x;
319         return ($1, $2);
320     }
321
322     sub _detect_parameterized_type_constraint {
323         $_[0] =~ m{ ^ $type_with_parameter $ }x;
324     }
325
326     sub _parse_type_constraint_union {
327         my $given = shift;
328         my @rv;
329         while ( $given =~ m{ \G (?: $op_union )? ($type) }gcx ) {
330                 push @rv => $1;
331         }
332         (pos($given) eq length($given))
333             || confess "'$given' didn't parse (parse-pos="
334                      . pos($given)
335                      . " and str-length="
336                      . length($given)
337                      . ")";
338         @rv;
339     }
340
341     sub _detect_type_constraint_union {
342         $_[0] =~ m{^ $type $op_union $type ( $op_union .* )? $}x;
343     }
344 }
345
346 ## --------------------------------------------------------
347 # define some basic built-in types
348 ## --------------------------------------------------------
349
350 type 'Any'  => where { 1 }; # meta-type including all
351 type 'Item' => where { 1 }; # base-type
352
353 subtype 'Undef'   => as 'Item' => where { !defined($_) };
354 subtype 'Defined' => as 'Item' => where {  defined($_) };
355
356 subtype 'Bool'
357     => as 'Item'
358     => where { !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq '0' };
359
360 subtype 'Value'
361     => as 'Defined'
362     => where { !ref($_) }
363     => optimize_as { defined($_[0]) && !ref($_[0]) };
364
365 subtype 'Ref'
366     => as 'Defined'
367     => where {  ref($_) }
368     => optimize_as { ref($_[0]) };
369
370 subtype 'Str'
371     => as 'Value'
372     => where { 1 }
373     => optimize_as { defined($_[0]) && !ref($_[0]) };
374
375 subtype 'Num'
376     => as 'Value'
377     => where { Scalar::Util::looks_like_number($_) }
378     => optimize_as { !ref($_[0]) && Scalar::Util::looks_like_number($_[0]) };
379
380 subtype 'Int'
381     => as 'Num'
382     => where { "$_" =~ /^-?[0-9]+$/ }
383     => optimize_as { defined($_[0]) && !ref($_[0]) && $_[0] =~ /^-?[0-9]+$/ };
384
385 subtype 'ScalarRef' => as 'Ref' => where { ref($_) eq 'SCALAR' } => optimize_as { ref($_[0]) eq 'SCALAR' };
386 subtype 'ArrayRef'  => as 'Ref' => where { ref($_) eq 'ARRAY'  } => optimize_as { ref($_[0]) eq 'ARRAY'  };
387 subtype 'HashRef'   => as 'Ref' => where { ref($_) eq 'HASH'   } => optimize_as { ref($_[0]) eq 'HASH'   };
388 subtype 'CodeRef'   => as 'Ref' => where { ref($_) eq 'CODE'   } => optimize_as { ref($_[0]) eq 'CODE'   };
389 subtype 'RegexpRef' => as 'Ref' => where { ref($_) eq 'Regexp' } => optimize_as { ref($_[0]) eq 'Regexp' };
390 subtype 'GlobRef'   => as 'Ref' => where { ref($_) eq 'GLOB'   } => optimize_as { ref($_[0]) eq 'GLOB'   };
391
392 # NOTE:
393 # scalar filehandles are GLOB refs,
394 # but a GLOB ref is not always a filehandle
395 subtype 'FileHandle'
396     => as 'GlobRef'
397     => where { Scalar::Util::openhandle($_) }
398     => optimize_as { ref($_[0]) eq 'GLOB' && Scalar::Util::openhandle($_[0]) };
399
400 # NOTE:
401 # blessed(qr/.../) returns true,.. how odd
402 subtype 'Object'
403     => as 'Ref'
404     => where { blessed($_) && blessed($_) ne 'Regexp' }
405     => optimize_as { blessed($_[0]) && blessed($_[0]) ne 'Regexp' };
406
407 subtype 'Role'
408     => as 'Object'
409     => where { $_->can('does') }
410     => optimize_as { blessed($_[0]) && $_[0]->can('does') };
411
412 subtype 'ClassName'
413     => as 'Str'
414     => where {
415          return unless defined($_) && length($_);
416
417          # walk the symbol table tree to avoid autovififying
418          # \*{${main::}{"Foo::"}} == \*main::Foo::
419
420          my $pack = \*::;
421          foreach my $part (split('::', $_)) {
422            return unless exists ${$$pack}{"${part}::"};
423            $pack = \*{${$$pack}{"${part}::"}};
424          }
425
426          # check for $VERSION or @ISA
427          return 1 if exists ${$$pack}{VERSION}
428                      && defined *{${$$pack}{VERSION}}{SCALAR};
429          return 1 if exists ${$$pack}{ISA}
430                      && defined *{${$$pack}{ISA}}{ARRAY};
431
432          # check for any method
433          foreach ( keys %{$$pack} ) {
434            next if substr($_, -2, 2) eq '::';
435            return 1 if defined *{${$$pack}{$_}}{CODE};
436          }
437
438          # fail
439          return;
440        }
441     => optimize_as {
442          return if ref($_[0]);
443          return unless defined($_[0]) && length($_[0]);
444
445          # walk the symbol table tree to avoid autovififying
446          # \*{${main::}{"Foo::"}} == \*main::Foo::
447
448          my $pack = \*::;
449          foreach my $part (split('::', $_[0])) {
450            return unless exists ${$$pack}{"${part}::"};
451            $pack = \*{${$$pack}{"${part}::"}};
452          }
453
454          # check for $VERSION or @ISA
455          return 1 if exists ${$$pack}{VERSION}
456                      && defined *{${$$pack}{VERSION}}{SCALAR};
457          return 1 if exists ${$$pack}{ISA}
458                      && defined *{${$$pack}{ISA}}{ARRAY};
459
460          # check for any method
461          foreach ( keys %{$$pack} ) {
462            next if substr($_, -2, 2) eq '::';
463            return 1 if defined *{${$$pack}{$_}}{CODE};
464          }
465
466          # fail
467          return;
468        };
469
470 ## --------------------------------------------------------
471 # end of built-in types ...
472 ## --------------------------------------------------------
473
474 {
475     my @BUILTINS = list_all_type_constraints();
476     sub list_all_builtin_type_constraints { @BUILTINS }
477 }
478
479 1;
480
481 __END__
482
483 =pod
484
485 =head1 NAME
486
487 Moose::Util::TypeConstraints - Type constraint system for Moose
488
489 =head1 SYNOPSIS
490
491   use Moose::Util::TypeConstraints;
492
493   type 'Num' => where { Scalar::Util::looks_like_number($_) };
494
495   subtype 'Natural'
496       => as 'Num'
497       => where { $_ > 0 };
498
499   subtype 'NaturalLessThanTen'
500       => as 'Natural'
501       => where { $_ < 10 }
502       => message { "This number ($_) is not less than ten!" };
503
504   coerce 'Num'
505       => from 'Str'
506         => via { 0+$_ };
507
508   enum 'RGBColors' => qw(red green blue);
509
510 =head1 DESCRIPTION
511
512 This module provides Moose with the ability to create custom type
513 contraints to be used in attribute definition.
514
515 =head2 Important Caveat
516
517 This is B<NOT> a type system for Perl 5. These are type constraints,
518 and they are not used by Moose unless you tell it to. No type
519 inference is performed, expression are not typed, etc. etc. etc.
520
521 This is simply a means of creating small constraint functions which
522 can be used to simplify your own type-checking code.
523
524 =head2 Slightly Less Important Caveat
525
526 It is almost always a good idea to quote your type and subtype names.
527 This is to prevent perl from trying to execute the call as an indirect
528 object call. This issue only seems to come up when you have a subtype
529 the same name as a valid class, but when the issue does arise it tends
530 to be quite annoying to debug.
531
532 So for instance, this:
533
534   subtype DateTime => as Object => where { $_->isa('DateTime') };
535
536 will I<Just Work>, while this:
537
538   use DateTime;
539   subtype DateTime => as Object => where { $_->isa('DateTime') };
540
541 will fail silently and cause many headaches. The simple way to solve
542 this, as well as future proof your subtypes from classes which have
543 yet to have been created yet, is to simply do this:
544
545   use DateTime;
546   subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') };
547
548 =head2 Default Type Constraints
549
550 This module also provides a simple hierarchy for Perl 5 types, this
551 could probably use some work, but it works for me at the moment.
552
553   Any
554   Item
555       Bool
556       Undef
557       Defined
558           Value
559               Num
560                 Int
561               Str
562                 ClassName
563           Ref
564               ScalarRef
565               ArrayRef
566               HashRef
567               CodeRef
568               RegexpRef
569               GlobRef
570                 FileHandle
571               Object
572                   Role
573
574 Suggestions for improvement are welcome.
575
576 B<NOTE:> The C<Undef> type constraint does not work correctly
577 in every occasion, please use it sparringly.
578
579 B<NOTE:> The C<ClassName> type constraint is simply a subtype
580 of string which responds true to C<isa('UNIVERSAL')>. This means
581 that your class B<must> be loaded for this type constraint to
582 pass. I know this is not ideal for all, but it is a saner
583 restriction than most others.
584
585 =head2 Use with Other Constraint Modules
586
587 This module should play fairly nicely with other constraint
588 modules with only some slight tweaking. The C<where> clause
589 in types is expected to be a C<CODE> reference which checks
590 it's first argument and returns a bool. Since most constraint
591 modules work in a similar way, it should be simple to adapt
592 them to work with Moose.
593
594 For instance, this is how you could use it with
595 L<Declare::Constraints::Simple> to declare a completely new type.
596
597   type 'HashOfArrayOfObjects'
598       => IsHashRef(
599           -keys   => HasLength,
600           -values => IsArrayRef( IsObject ));
601
602 For more examples see the F<t/204_example_w_DCS.t> test file.
603
604 Here is an example of using L<Test::Deep> and it's non-test
605 related C<eq_deeply> function.
606
607   type 'ArrayOfHashOfBarsAndRandomNumbers'
608       => where {
609           eq_deeply($_,
610               array_each(subhashof({
611                   bar           => isa('Bar'),
612                   random_number => ignore()
613               })))
614         };
615
616 For a complete example see the F<t/205_example_w_TestDeep.t>
617 test file.
618
619 =head1 FUNCTIONS
620
621 =head2 Type Constraint Construction & Locating
622
623 =over 4
624
625 =item B<create_type_constraint_union ($pipe_seperated_types | @type_constraint_names)>
626
627 Given string with C<$pipe_seperated_types> or a list of C<@type_constraint_names>,
628 this will return a L<Moose::Meta::TypeConstraint::Union> instance.
629
630 =item B<create_parameterized_type_constraint ($type_name)>
631
632 Given a C<$type_name> in the form of:
633
634   BaseType[ContainerType]
635
636 this will extract the base type and container type and build an instance of
637 L<Moose::Meta::TypeConstraint::Parameterized> for it.
638
639 =item B<find_or_create_type_constraint ($type_name, ?$options_for_anon_type)>
640
641 This will attempt to find or create a type constraint given the a C<$type_name>.
642 If it cannot find it in the registry, it will see if it should be a union or
643 container type an create one if appropriate, and lastly if nothing can be
644 found or created that way, it will create an anon-type using the
645 C<$options_for_anon_type> HASH ref to populate it.
646
647 =item B<find_type_constraint ($type_name)>
648
649 This function can be used to locate a specific type constraint
650 meta-object, of the class L<Moose::Meta::TypeConstraint> or a
651 derivative. What you do with it from there is up to you :)
652
653 =item B<get_type_constraint_registry>
654
655 Fetch the L<Moose::Meta::TypeConstraint::Registry> object which
656 keeps track of all type constraints.
657
658 =item B<list_all_type_constraints>
659
660 This will return a list of type constraint names, you can then
661 fetch them using C<find_type_constraint ($type_name)> if you
662 want to.
663
664 =item B<list_all_builtin_type_constraints>
665
666 This will return a list of builtin type constraints, meaning,
667 those which are defined in this module. See the section
668 labeled L<Default Type Constraints> for a complete list.
669
670 =item B<export_type_constraints_as_functions>
671
672 This will export all the current type constraints as functions
673 into the caller's namespace. Right now, this is mostly used for
674 testing, but it might prove useful to others.
675
676 =back
677
678 =head2 Type Constraint Constructors
679
680 The following functions are used to create type constraints.
681 They will then register the type constraints in a global store
682 where Moose can get to them if it needs to.
683
684 See the L<SYNOPSIS> for an example of how to use these.
685
686 =over 4
687
688 =item B<type ($name, $where_clause)>
689
690 This creates a base type, which has no parent.
691
692 =item B<subtype ($name, $parent, $where_clause, ?$message)>
693
694 This creates a named subtype.
695
696 =item B<subtype ($parent, $where_clause, ?$message)>
697
698 This creates an unnamed subtype and will return the type
699 constraint meta-object, which will be an instance of
700 L<Moose::Meta::TypeConstraint>.
701
702 =item B<enum ($name, @values)>
703
704 This will create a basic subtype for a given set of strings.
705 The resulting constraint will be a subtype of C<Str> and
706 will match any of the items in C<@values>. It is case sensitive.
707 See the L<SYNOPSIS> for a simple example.
708
709 B<NOTE:> This is not a true proper enum type, it is simple
710 a convient constraint builder.
711
712 =item B<as>
713
714 This is just sugar for the type constraint construction syntax.
715
716 =item B<where>
717
718 This is just sugar for the type constraint construction syntax.
719
720 =item B<message>
721
722 This is just sugar for the type constraint construction syntax.
723
724 =item B<optimize_as>
725
726 This can be used to define a "hand optimized" version of your
727 type constraint which can be used to avoid traversing a subtype
728 constraint heirarchy.
729
730 B<NOTE:> You should only use this if you know what you are doing,
731 all the built in types use this, so your subtypes (assuming they
732 are shallow) will not likely need to use this.
733
734 =back
735
736 =head2 Type Coercion Constructors
737
738 Type constraints can also contain type coercions as well. If you
739 ask your accessor to coerce, then Moose will run the type-coercion
740 code first, followed by the type constraint check. This feature
741 should be used carefully as it is very powerful and could easily
742 take off a limb if you are not careful.
743
744 See the L<SYNOPSIS> for an example of how to use these.
745
746 =over 4
747
748 =item B<coerce>
749
750 =item B<from>
751
752 This is just sugar for the type coercion construction syntax.
753
754 =item B<via>
755
756 This is just sugar for the type coercion construction syntax.
757
758 =back
759
760 =head2 Namespace Management
761
762 =over 4
763
764 =item B<unimport>
765
766 This will remove all the type constraint keywords from the
767 calling class namespace.
768
769 =back
770
771 =head1 BUGS
772
773 All complex software has bugs lurking in it, and this module is no
774 exception. If you find a bug please either email me, or add the bug
775 to cpan-RT.
776
777 =head1 AUTHOR
778
779 Stevan Little E<lt>stevan@iinteractive.comE<gt>
780
781 =head1 COPYRIGHT AND LICENSE
782
783 Copyright 2006, 2007 by Infinity Interactive, Inc.
784
785 L<http://www.iinteractive.com>
786
787 This library is free software; you can redistribute it and/or modify
788 it under the same terms as Perl itself.
789
790 =cut