allow overriding class and role types with equivalent types
[gitmo/Moose.git] / lib / Moose / Util / TypeConstraints.pm
CommitLineData
a15dff8d 1
2package Moose::Util::TypeConstraints;
3
998a8a25 4use Carp ();
9e856c83 5use List::MoreUtils qw( all any );
9a63faba 6use Scalar::Util qw( blessed reftype );
e606ae5f 7use Moose::Exporter;
a15dff8d 8
d9b40005 9## --------------------------------------------------------
e85d2a5d 10# Prototyped subs must be predeclared because we have a
11# circular dependency with Moose::Meta::Attribute et. al.
12# so in case of us being use'd first the predeclaration
d9b40005 13# ensures the prototypes are in scope when consumers are
14# compiled.
15
d9b40005 16# dah sugah!
180899ed 17sub where (&);
18sub via (&);
19sub message (&);
d9b40005 20sub optimize_as (&);
4e36cf24 21sub inline_as (&);
d9b40005 22
d9b40005 23## --------------------------------------------------------
8c4acc60 24
1fa1a58d 25use Moose::Deprecated;
4e036ee4 26use Moose::Meta::TypeConstraint;
3726f905 27use Moose::Meta::TypeConstraint::Union;
0fbd4b0a 28use Moose::Meta::TypeConstraint::Parameterized;
7e4e1ad4 29use Moose::Meta::TypeConstraint::Parameterizable;
620db045 30use Moose::Meta::TypeConstraint::Class;
31use Moose::Meta::TypeConstraint::Role;
dabed765 32use Moose::Meta::TypeConstraint::Enum;
0a6bff54 33use Moose::Meta::TypeConstraint::DuckType;
2ca63f5d 34use Moose::Meta::TypeCoercion;
3726f905 35use Moose::Meta::TypeCoercion::Union;
22aed3c0 36use Moose::Meta::TypeConstraint::Registry;
4e036ee4 37
e606ae5f 38Moose::Exporter->setup_import_methods(
39 as_is => [
40 qw(
180899ed 41 type subtype class_type role_type maybe_type duck_type
7afaa906 42 as where message optimize_as inline_as
e606ae5f 43 coerce from via
0faea2a8 44 enum union
e606ae5f 45 find_type_constraint
0d29b772 46 register_type_constraint
47 match_on_type )
e606ae5f 48 ],
e606ae5f 49);
a15dff8d 50
d9b40005 51## --------------------------------------------------------
52## type registry and some useful functions for it
53## --------------------------------------------------------
54
22aed3c0 55my $REGISTRY = Moose::Meta::TypeConstraint::Registry->new;
587ae0d2 56
180899ed 57sub get_type_constraint_registry {$REGISTRY}
58sub list_all_type_constraints { keys %{ $REGISTRY->type_constraints } }
59
d9b40005 60sub export_type_constraints_as_functions {
61 my $pkg = caller();
62 no strict 'refs';
180899ed 63 foreach my $constraint ( keys %{ $REGISTRY->type_constraints } ) {
64 my $tc = $REGISTRY->get_type_constraint($constraint)
65 ->_compiled_type_constraint;
66 *{"${pkg}::${constraint}"}
67 = sub { $tc->( $_[0] ) ? 1 : undef }; # the undef is for compat
a0f8153d 68 }
d9b40005 69}
182134e8 70
0c015f1b 71sub create_type_constraint_union {
8ac5be59 72 _create_type_constraint_union(\@_);
182134e8 73}
a15dff8d 74
a46050ae 75sub create_named_type_constraint_union {
76 my $name = shift;
8ac5be59 77 _create_type_constraint_union($name, \@_);
78}
79
80sub _create_type_constraint_union {
81 my $name;
82 $name = shift if @_ > 1;
83 my @tcs = @{ shift() };
84
a46050ae 85 my @type_constraint_names;
86
8ac5be59 87 if ( scalar @tcs == 1 && _detect_type_constraint_union( $tcs[0] ) ) {
88 @type_constraint_names = _parse_type_constraint_union( $tcs[0] );
a46050ae 89 }
90 else {
8ac5be59 91 @type_constraint_names = @tcs;
a46050ae 92 }
93
94 ( scalar @type_constraint_names >= 2 )
95 || __PACKAGE__->_throw_error(
96 "You must pass in at least 2 type names to make a union");
97
98 my @type_constraints = map {
99 find_or_parse_type_constraint($_)
100 || __PACKAGE__->_throw_error(
101 "Could not locate type constraint ($_) for the union");
102 } @type_constraint_names;
103
104 my %options = (
105 type_constraints => \@type_constraints
106 );
107 $options{name} = $name if defined $name;
108
109 return Moose::Meta::TypeConstraint::Union->new(%options);
110}
111
112
0c015f1b 113sub create_parameterized_type_constraint {
d9b40005 114 my $type_constraint_name = shift;
180899ed 115 my ( $base_type, $type_parameter )
116 = _parse_parameterized_type_constraint($type_constraint_name);
e85d2a5d 117
180899ed 118 ( defined $base_type && defined $type_parameter )
119 || __PACKAGE__->_throw_error(
120 "Could not parse type name ($type_constraint_name) correctly");
e85d2a5d 121
180899ed 122 if ( $REGISTRY->has_type_constraint($base_type) ) {
90e78884 123 my $base_type_tc = $REGISTRY->get_type_constraint($base_type);
124 return _create_parameterized_type_constraint(
125 $base_type_tc,
126 $type_parameter
127 );
180899ed 128 }
129 else {
130 __PACKAGE__->_throw_error(
131 "Could not locate the base type ($base_type)");
90e78884 132 }
22aed3c0 133}
134
90e78884 135sub _create_parameterized_type_constraint {
136 my ( $base_type_tc, $type_parameter ) = @_;
137 if ( $base_type_tc->can('parameterize') ) {
138 return $base_type_tc->parameterize($type_parameter);
180899ed 139 }
140 else {
90e78884 141 return Moose::Meta::TypeConstraint::Parameterized->new(
180899ed 142 name => $base_type_tc->name . '[' . $type_parameter . ']',
90e78884 143 parent => $base_type_tc,
180899ed 144 type_parameter =>
145 find_or_create_isa_type_constraint($type_parameter),
90e78884 146 );
147 }
180899ed 148}
90e78884 149
4ab662d6 150#should we also support optimized checks?
0c015f1b 151sub create_class_type_constraint {
620db045 152 my ( $class, $options ) = @_;
153
180899ed 154# too early for this check
155#find_type_constraint("ClassName")->check($class)
156# || __PACKAGE__->_throw_error("Can't create a class type constraint because '$class' is not a class name");
3fef8ce8 157
8eddcf9e 158 my $pkg_defined_in = scalar( caller(1) );
159
c8bb956a 160 if (my $type = $REGISTRY->get_type_constraint($class)) {
6f496445 161 if (!($type->isa('Moose::Meta::TypeConstraint::Class') && $type->class eq $class)) {
162 _confess(
163 "The type constraint '$class' has already been created in "
164 . $type->_package_defined_in
165 . " and cannot be created again in "
166 . $pkg_defined_in )
167 }
c8bb956a 168 }
169
620db045 170 my %options = (
8eddcf9e 171 class => $class,
172 name => $class,
173 package_defined_in => $pkg_defined_in,
620db045 174 %{ $options || {} },
4ab662d6 175 );
620db045 176
177 $options{name} ||= "__ANON__";
178
510d13e1 179 my $tc = Moose::Meta::TypeConstraint::Class->new(%options);
180 $REGISTRY->add_type_constraint($tc);
181 return $tc;
3fef8ce8 182}
183
0c015f1b 184sub create_role_type_constraint {
620db045 185 my ( $role, $options ) = @_;
e85d2a5d 186
180899ed 187# too early for this check
188#find_type_constraint("ClassName")->check($class)
189# || __PACKAGE__->_throw_error("Can't create a class type constraint because '$class' is not a class name");
e85d2a5d 190
8eddcf9e 191 my $pkg_defined_in = scalar( caller(1) );
192
c8bb956a 193 if (my $type = $REGISTRY->get_type_constraint($role)) {
6f496445 194 if (!($type->isa('Moose::Meta::TypeConstraint::Role') && $type->role eq $role)) {
195 _confess(
196 "The type constraint '$role' has already been created in "
197 . $type->_package_defined_in
198 . " and cannot be created again in "
199 . $pkg_defined_in )
200 }
c8bb956a 201 }
202
620db045 203 my %options = (
8eddcf9e 204 role => $role,
205 name => $role,
206 package_defined_in => $pkg_defined_in,
620db045 207 %{ $options || {} },
208 );
e85d2a5d 209
620db045 210 $options{name} ||= "__ANON__";
211
510d13e1 212 my $tc = Moose::Meta::TypeConstraint::Role->new(%options);
213 $REGISTRY->add_type_constraint($tc);
214 return $tc;
620db045 215}
216
0c015f1b 217sub find_or_create_type_constraint {
620db045 218 my ( $type_constraint_name, $options_for_anon_type ) = @_;
219
180899ed 220 if ( my $constraint
221 = find_or_parse_type_constraint($type_constraint_name) ) {
620db045 222 return $constraint;
d9b40005 223 }
620db045 224 elsif ( defined $options_for_anon_type ) {
180899ed 225
d9b40005 226 # NOTE:
4ab662d6 227 # if there is no $options_for_anon_type
228 # specified, then we assume they don't
f3c4e20e 229 # want to create one, and return nothing.
f3c4e20e 230
d9b40005 231 # otherwise assume that we should create
e85d2a5d 232 # an ANON type with the $options_for_anon_type
d9b40005 233 # options which can be passed in. It should
e85d2a5d 234 # be noted that these don't get registered
d9b40005 235 # so we need to return it.
236 # - SL
237 return Moose::Meta::TypeConstraint->new(
238 name => '__ANON__',
e85d2a5d 239 %{$options_for_anon_type}
d9b40005 240 );
241 }
e85d2a5d 242
620db045 243 return;
244}
245
0c015f1b 246sub find_or_create_isa_type_constraint {
620db045 247 my $type_constraint_name = shift;
180899ed 248 find_or_parse_type_constraint($type_constraint_name)
249 || create_class_type_constraint($type_constraint_name);
620db045 250}
251
0c015f1b 252sub find_or_create_does_type_constraint {
620db045 253 my $type_constraint_name = shift;
180899ed 254 find_or_parse_type_constraint($type_constraint_name)
255 || create_role_type_constraint($type_constraint_name);
620db045 256}
257
0c015f1b 258sub find_or_parse_type_constraint {
eb4c4e82 259 my $type_constraint_name = normalize_type_constraint_name(shift);
620db045 260 my $constraint;
180899ed 261
262 if ( $constraint = find_type_constraint($type_constraint_name) ) {
e606ae5f 263 return $constraint;
180899ed 264 }
265 elsif ( _detect_type_constraint_union($type_constraint_name) ) {
620db045 266 $constraint = create_type_constraint_union($type_constraint_name);
180899ed 267 }
268 elsif ( _detect_parameterized_type_constraint($type_constraint_name) ) {
269 $constraint
270 = create_parameterized_type_constraint($type_constraint_name);
271 }
272 else {
620db045 273 return;
274 }
bb6c8335 275
d9b40005 276 $REGISTRY->add_type_constraint($constraint);
e85d2a5d 277 return $constraint;
d9b40005 278}
22aed3c0 279
eb4c4e82 280sub normalize_type_constraint_name {
84a9c64c 281 my $type_constraint_name = shift;
c8f663b2 282 $type_constraint_name =~ s/\s//g;
eb4c4e82 283 return $type_constraint_name;
284}
285
5f223879 286sub _confess {
287 my $error = shift;
288
289 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
290 Carp::confess($error);
291}
292
22aed3c0 293## --------------------------------------------------------
294## exported functions ...
295## --------------------------------------------------------
296
0c015f1b 297sub find_type_constraint {
eeedfc8a 298 my $type = shift;
299
300 if ( blessed $type and $type->isa("Moose::Meta::TypeConstraint") ) {
301 return $type;
e606ae5f 302 }
303 else {
304 return unless $REGISTRY->has_type_constraint($type);
eeedfc8a 305 return $REGISTRY->get_type_constraint($type);
306 }
307}
22aed3c0 308
0c015f1b 309sub register_type_constraint {
3fef8ce8 310 my $constraint = shift;
180899ed 311 __PACKAGE__->_throw_error("can't register an unnamed type constraint")
312 unless defined $constraint->name;
3fef8ce8 313 $REGISTRY->add_type_constraint($constraint);
dabed765 314 return $constraint;
3fef8ce8 315}
316
7c13858b 317# type constructors
a15dff8d 318
9c27968f 319sub type {
9e856c83 320 my $name = shift;
9a63faba 321
9e856c83 322 my %p = map { %{$_} } @_;
323
180899ed 324 return _create_type_constraint(
325 $name, undef, $p{where}, $p{message},
4e36cf24 326 $p{optimize_as}, $p{inline_as},
180899ed 327 );
a15dff8d 328}
329
9c27968f 330sub subtype {
180899ed 331 if ( @_ == 1 && !ref $_[0] ) {
332 __PACKAGE__->_throw_error(
333 'A subtype cannot consist solely of a name, it must have a parent'
334 );
f75f625d 335 }
336
f6c0c589 337 # The blessed check is mostly to accommodate MooseX::Types, which
338 # uses an object which overloads stringification as a type name.
180899ed 339 my $name = ref $_[0] && !blessed $_[0] ? undef : shift;
9a63faba 340
341 my %p = map { %{$_} } @_;
342
343 # subtype Str => where { ... };
180899ed 344 if ( !exists $p{as} ) {
9e856c83 345 $p{as} = $name;
9a63faba 346 $name = undef;
347 }
348
180899ed 349 return _create_type_constraint(
350 $name, $p{as}, $p{where}, $p{message},
4e36cf24 351 $p{optimize_as}, $p{inline_as},
180899ed 352 );
a15dff8d 353}
354
9c27968f 355sub class_type {
510d13e1 356 create_class_type_constraint(@_);
3fef8ce8 357}
358
620db045 359sub role_type ($;$) {
510d13e1 360 create_role_type_constraint(@_);
620db045 361}
362
1b2c9bda 363sub maybe_type {
364 my ($type_parameter) = @_;
365
28ce1444 366 register_type_constraint(
ed7060d9 367 $REGISTRY->get_type_constraint('Maybe')->parameterize($type_parameter)
28ce1444 368 );
1b2c9bda 369}
370
180899ed 371sub duck_type {
cdacfaf3 372 my ( $type_name, @methods ) = @_;
180899ed 373 if ( ref $type_name eq 'ARRAY' && !@methods ) {
cdacfaf3 374 @methods = @$type_name;
180899ed 375 $type_name = undef;
376 }
bce5d4a5 377 if ( @methods == 1 && ref $methods[0] eq 'ARRAY' ) {
378 @methods = @{ $methods[0] };
379 }
180899ed 380
381 register_type_constraint(
0a6bff54 382 create_duck_type_constraint(
cdacfaf3 383 $type_name,
0a6bff54 384 \@methods,
180899ed 385 )
386 );
387}
388
9c27968f 389sub coerce {
180899ed 390 my ( $type_name, @coercion_map ) = @_;
391 _install_type_coercions( $type_name, \@coercion_map );
182134e8 392}
393
f6c0c589 394# The trick of returning @_ lets us avoid having to specify a
395# prototype. Perl will parse this:
396#
397# subtype 'Foo'
398# => as 'Str'
399# => where { ... }
400#
401# as this:
402#
403# subtype( 'Foo', as( 'Str', where { ... } ) );
404#
69229b40 405# If as() returns all its extra arguments, this just works, and
f6c0c589 406# preserves backwards compatibility.
180899ed 407sub as { { as => shift }, @_ }
9e856c83 408sub where (&) { { where => $_[0] } }
409sub message (&) { { message => $_[0] } }
410sub optimize_as (&) { { optimize_as => $_[0] } }
4e36cf24 411sub inline_as (&) { { inline_as => $_[0] } }
8ecb1fa0 412
9a63faba 413sub from {@_}
414sub via (&) { $_[0] }
a15dff8d 415
9c27968f 416sub enum {
180899ed 417 my ( $type_name, @values ) = @_;
418
4ab662d6 419 # NOTE:
420 # if only an array-ref is passed then
9f4334a1 421 # you get an anon-enum
422 # - SL
f6af1028 423 if ( ref $type_name eq 'ARRAY' ) {
424 @values == 0
425 || __PACKAGE__->_throw_error("enum called with an array reference and additional arguments. Did you mean to parenthesize the enum call's parameters?");
426
9f4334a1 427 @values = @$type_name;
428 $type_name = undef;
429 }
bce5d4a5 430 if ( @values == 1 && ref $values[0] eq 'ARRAY' ) {
431 @values = @{ $values[0] };
432 }
dabed765 433
434 register_type_constraint(
435 create_enum_type_constraint(
436 $type_name,
437 \@values,
438 )
439 );
440}
441
0faea2a8 442sub union {
443 my ( $type_name, @constraints ) = @_;
444 if ( ref $type_name eq 'ARRAY' ) {
445 @constraints == 0
446 || __PACKAGE__->_throw_error("union called with an array reference and additional arguments.");
447 @constraints = @$type_name;
448 $type_name = undef;
449 }
450 if ( @constraints == 1 && ref $constraints[0] eq 'ARRAY' ) {
451 @constraints = @{ $constraints[0] };
452 }
0faea2a8 453 if ( defined $type_name ) {
a46050ae 454 return register_type_constraint(
455 create_named_type_constraint_union( $type_name, @constraints )
456 );
0faea2a8 457 }
a46050ae 458 return create_type_constraint_union( @constraints );
0faea2a8 459}
460
0c015f1b 461sub create_enum_type_constraint {
dabed765 462 my ( $type_name, $values ) = @_;
e606ae5f 463
dabed765 464 Moose::Meta::TypeConstraint::Enum->new(
180899ed 465 name => $type_name || '__ANON__',
dabed765 466 values => $values,
a0f8153d 467 );
fcec2383 468}
469
0a6bff54 470sub create_duck_type_constraint {
471 my ( $type_name, $methods ) = @_;
472
473 Moose::Meta::TypeConstraint::DuckType->new(
474 name => $type_name || '__ANON__',
475 methods => $methods,
476 );
477}
478
0d29b772 479sub match_on_type {
480 my ($to_match, @cases) = @_;
481 my $default;
482 if (@cases % 2 != 0) {
483 $default = pop @cases;
484 (ref $default eq 'CODE')
485 || __PACKAGE__->_throw_error("Default case must be a CODE ref, not $default");
486 }
487 while (@cases) {
488 my ($type, $action) = splice @cases, 0, 2;
489
490 unless (blessed $type && $type->isa('Moose::Meta::TypeConstraint')) {
491 $type = find_or_parse_type_constraint($type)
492 || __PACKAGE__->_throw_error("Cannot find or parse the type '$type'")
493 }
494
495 (ref $action eq 'CODE')
496 || __PACKAGE__->_throw_error("Match action must be a CODE ref, not $action");
497
498 if ($type->check($to_match)) {
499 local $_ = $to_match;
500 return $action->($to_match);
501 }
502 }
1d39d709 503 (defined $default)
504 || __PACKAGE__->_throw_error("No cases matched for $to_match");
0d29b772 505 {
506 local $_ = $to_match;
1d39d709 507 return $default->($to_match);
0d29b772 508 }
509}
510
511
d9b40005 512## --------------------------------------------------------
513## desugaring functions ...
514## --------------------------------------------------------
515
e85d2a5d 516sub _create_type_constraint ($$$;$$) {
9a63faba 517 my $name = shift;
518 my $parent = shift;
519 my $check = shift;
520 my $message = shift;
521 my $optimized = shift;
4e36cf24 522 my $inlined = shift;
d9b40005 523
9a63faba 524 my $pkg_defined_in = scalar( caller(1) );
e85d2a5d 525
1da6728b 526 if ( defined $name ) {
d9b40005 527 my $type = $REGISTRY->get_type_constraint($name);
e85d2a5d 528
5f223879 529 ( $type->_package_defined_in eq $pkg_defined_in )
530 || _confess(
531 "The type constraint '$name' has already been created in "
532 . $type->_package_defined_in
533 . " and cannot be created again in "
534 . $pkg_defined_in )
535 if defined $type;
eee1a213 536
537 $name =~ /^[\w:\.]+$/
538 or die qq{$name contains invalid characters for a type name.}
33c8a6d0 539 . qq{ Names can contain alphanumeric character, ":", and "."\n};
e85d2a5d 540 }
1da6728b 541
9ceb576e 542 my %opts = (
9a63faba 543 name => $name,
d9b40005 544 package_defined_in => $pkg_defined_in,
e85d2a5d 545
1da6728b 546 ( $check ? ( constraint => $check ) : () ),
547 ( $message ? ( message => $message ) : () ),
548 ( $optimized ? ( optimized => $optimized ) : () ),
4e36cf24 549 ( $inlined ? ( inlined => $inlined ) : () ),
d9b40005 550 );
1da6728b 551
9ceb576e 552 my $constraint;
180899ed 553 if (
554 defined $parent
1da6728b 555 and $parent
180899ed 556 = blessed $parent
557 ? $parent
558 : find_or_create_isa_type_constraint($parent)
559 ) {
85a9908f 560 $constraint = $parent->create_child_type(%opts);
1da6728b 561 }
562 else {
563 $constraint = Moose::Meta::TypeConstraint->new(%opts);
4ab662d6 564 }
d9b40005 565
566 $REGISTRY->add_type_constraint($constraint)
567 if defined $name;
568
569 return $constraint;
570}
571
e85d2a5d 572sub _install_type_coercions ($$) {
180899ed 573 my ( $type_name, $coercion_map ) = @_;
e606ae5f 574 my $type = find_type_constraint($type_name);
180899ed 575 ( defined $type )
576 || __PACKAGE__->_throw_error(
a885c019 577 "Cannot find type '$type_name', perhaps you forgot to load it");
180899ed 578 if ( $type->has_coercion ) {
41e007e4 579 $type->coercion->add_type_coercions(@$coercion_map);
580 }
581 else {
582 my $type_coercion = Moose::Meta::TypeCoercion->new(
583 type_coercion_map => $coercion_map,
584 type_constraint => $type
585 );
586 $type->coercion($type_coercion);
587 }
d9b40005 588}
589
590## --------------------------------------------------------
f1917f58 591## type notation parsing ...
592## --------------------------------------------------------
593
594{
180899ed 595
e85d2a5d 596 # All I have to say is mugwump++ cause I know
597 # do not even have enough regexp-fu to be able
598 # to have written this (I can only barely
f1917f58 599 # understand it as it is)
e85d2a5d 600 # - SL
601
f1917f58 602 use re "eval";
603
eee1a213 604 my $valid_chars = qr{[\w:\.]};
68d5a469 605 my $type_atom = qr{ (?>$valid_chars+) }x;
68113f48 606 my $ws = qr{ (?>\s*) }x;
607 my $op_union = qr{ $ws \| $ws }x;
608
609 my ($type, $type_capture_parts, $type_with_parameter, $union, $any);
610 if (Class::MOP::IS_RUNNING_ON_5_10) {
611 my $type_pattern
612 = q{ (?&type_atom) (?: \[ (?&ws) (?&any) (?&ws) \] )? };
613 my $type_capture_parts_pattern
614 = q{ ((?&type_atom)) (?: \[ (?&ws) ((?&any)) (?&ws) \] )? };
615 my $type_with_parameter_pattern
616 = q{ (?&type_atom) \[ (?&ws) (?&any) (?&ws) \] };
617 my $union_pattern
618 = q{ (?&type) (?> (?: (?&op_union) (?&type) )+ ) };
619 my $any_pattern
620 = q{ (?&type) | (?&union) };
621
622 my $defines = qr{(?(DEFINE)
623 (?<valid_chars> $valid_chars)
624 (?<type_atom> $type_atom)
625 (?<ws> $ws)
626 (?<op_union> $op_union)
627 (?<type> $type_pattern)
628 (?<type_capture_parts> $type_capture_parts_pattern)
629 (?<type_with_parameter> $type_with_parameter_pattern)
630 (?<union> $union_pattern)
631 (?<any> $any_pattern)
632 )}x;
633
634 $type = qr{ $type_pattern $defines }x;
635 $type_capture_parts = qr{ $type_capture_parts_pattern $defines }x;
636 $type_with_parameter = qr{ $type_with_parameter_pattern $defines }x;
637 $union = qr{ $union_pattern $defines }x;
638 $any = qr{ $any_pattern $defines }x;
639 }
640 else {
641 $type
642 = qr{ $type_atom (?: \[ $ws (??{$any}) $ws \] )? }x;
643 $type_capture_parts
644 = qr{ ($type_atom) (?: \[ $ws ((??{$any})) $ws \] )? }x;
645 $type_with_parameter
646 = qr{ $type_atom \[ $ws (??{$any}) $ws \] }x;
647 $union
648 = qr{ $type (?> (?: $op_union $type )+ ) }x;
649 $any
650 = qr{ $type | $union }x;
651 }
f1917f58 652
f1917f58 653
0fbd4b0a 654 sub _parse_parameterized_type_constraint {
180899ed 655 { no warnings 'void'; $any; } # force capture of interpolated lexical
84a9c64c 656 $_[0] =~ m{ $type_capture_parts }x;
180899ed 657 return ( $1, $2 );
f1917f58 658 }
659
0fbd4b0a 660 sub _detect_parameterized_type_constraint {
180899ed 661 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 662 $_[0] =~ m{ ^ $type_with_parameter $ }x;
f1917f58 663 }
664
665 sub _parse_type_constraint_union {
180899ed 666 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 667 my $given = shift;
668 my @rv;
669 while ( $given =~ m{ \G (?: $op_union )? ($type) }gcx ) {
82a5b1a7 670 push @rv => $1;
e85d2a5d 671 }
180899ed 672 ( pos($given) eq length($given) )
673 || __PACKAGE__->_throw_error( "'$given' didn't parse (parse-pos="
674 . pos($given)
675 . " and str-length="
676 . length($given)
677 . ")" );
e85d2a5d 678 @rv;
f1917f58 679 }
680
681 sub _detect_type_constraint_union {
180899ed 682 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 683 $_[0] =~ m{^ $type $op_union $type ( $op_union .* )? $}x;
f1917f58 684 }
685}
686
687## --------------------------------------------------------
d9b40005 688# define some basic built-in types
689## --------------------------------------------------------
a15dff8d 690
06d02aac 691# By making these classes immutable before creating all the types in
692# Moose::Util::TypeConstraints::Builtin , we avoid repeatedly calling the slow
693# MOP-based accessors.
3cae4250 694$_->make_immutable(
695 inline_constructor => 1,
696 constructor_name => "_new",
697
698 # these are Class::MOP accessors, so they need inlining
699 inline_accessors => 1
700 ) for grep { $_->is_mutable }
37edf27e 701 map { Class::MOP::class_of($_) }
3cae4250 702 qw(
703 Moose::Meta::TypeConstraint
704 Moose::Meta::TypeConstraint::Union
705 Moose::Meta::TypeConstraint::Parameterized
706 Moose::Meta::TypeConstraint::Parameterizable
707 Moose::Meta::TypeConstraint::Class
708 Moose::Meta::TypeConstraint::Role
709 Moose::Meta::TypeConstraint::Enum
0a6bff54 710 Moose::Meta::TypeConstraint::DuckType
3cae4250 711 Moose::Meta::TypeConstraint::Registry
712);
713
06d02aac 714require Moose::Util::TypeConstraints::Builtins;
715Moose::Util::TypeConstraints::Builtins::define_builtins($REGISTRY);
7e4e1ad4 716
180899ed 717my @PARAMETERIZABLE_TYPES
2c29c0e7 718 = map { $REGISTRY->get_type_constraint($_) } qw[ScalarRef ArrayRef HashRef Maybe];
180899ed 719
720sub get_all_parameterizable_types {@PARAMETERIZABLE_TYPES}
7e4e1ad4 721
4ab662d6 722sub add_parameterizable_type {
7e4e1ad4 723 my $type = shift;
180899ed 724 ( blessed $type
725 && $type->isa('Moose::Meta::TypeConstraint::Parameterizable') )
726 || __PACKAGE__->_throw_error(
727 "Type must be a Moose::Meta::TypeConstraint::Parameterizable not $type"
728 );
7e4e1ad4 729 push @PARAMETERIZABLE_TYPES => $type;
4ab662d6 730}
7e4e1ad4 731
732## --------------------------------------------------------
d9b40005 733# end of built-in types ...
734## --------------------------------------------------------
735
943596a6 736{
737 my @BUILTINS = list_all_type_constraints();
180899ed 738 sub list_all_builtin_type_constraints {@BUILTINS}
943596a6 739}
740
6ea98933 741sub _throw_error {
6b83828f 742 shift;
6ea98933 743 require Moose;
744 unshift @_, 'Moose';
745 goto &Moose::throw_error;
746}
747
a15dff8d 7481;
749
ad46f524 750# ABSTRACT: Type constraint system for Moose
751
a15dff8d 752__END__
753
754=pod
755
a15dff8d 756=head1 SYNOPSIS
757
758 use Moose::Util::TypeConstraints;
759
04eec387 760 subtype 'Natural',
761 as 'Int',
762 where { $_ > 0 };
e85d2a5d 763
04eec387 764 subtype 'NaturalLessThanTen',
765 as 'Natural',
766 where { $_ < 10 },
767 message { "This number ($_) is not less than ten!" };
e85d2a5d 768
04eec387 769 coerce 'Num',
770 from 'Str',
771 via { 0+$_ };
e85d2a5d 772
00954dd1 773 class_type 'DateTimeClass', { class => 'DateTime' };
83aa5247 774
775 role_type 'Barks', { role => 'Some::Library::Role::Barks' };
776
04eec387 777 enum 'RGBColors', [qw(red green blue)];
a15dff8d 778
74dccf76 779 union 'StringOrArray', [qw( String Array )];
780
e7fcb7b2 781 no Moose::Util::TypeConstraints;
782
a15dff8d 783=head1 DESCRIPTION
784
e85d2a5d 785This module provides Moose with the ability to create custom type
6549b0d1 786constraints to be used in attribute definition.
e522431d 787
6ba6d68c 788=head2 Important Caveat
789
e85d2a5d 790This is B<NOT> a type system for Perl 5. These are type constraints,
791and they are not used by Moose unless you tell it to. No type
e7fcb7b2 792inference is performed, expressions are not typed, etc. etc. etc.
6ba6d68c 793
e7fcb7b2 794A type constraint is at heart a small "check if a value is valid"
795function. A constraint can be associated with an attribute. This
796simplifies parameter validation, and makes your code clearer to read,
797because you can refer to constraints by name.
6ba6d68c 798
2c0cbef7 799=head2 Slightly Less Important Caveat
800
e7fcb7b2 801It is B<always> a good idea to quote your type names.
004222dc 802
e7fcb7b2 803This prevents Perl from trying to execute the call as an indirect
804object call. This can be an issue when you have a subtype with the
805same name as a valid class.
2c0cbef7 806
e7fcb7b2 807For instance:
e85d2a5d 808
2c0cbef7 809 subtype DateTime => as Object => where { $_->isa('DateTime') };
810
e7fcb7b2 811will I<just work>, while this:
2c0cbef7 812
813 use DateTime;
814 subtype DateTime => as Object => where { $_->isa('DateTime') };
815
e85d2a5d 816will fail silently and cause many headaches. The simple way to solve
817this, as well as future proof your subtypes from classes which have
e7fcb7b2 818yet to have been created, is to quote the type name:
2c0cbef7 819
820 use DateTime;
04eec387 821 subtype 'DateTime', as 'Object', where { $_->isa('DateTime') };
2c0cbef7 822
6ba6d68c 823=head2 Default Type Constraints
e522431d 824
e606ae5f 825This module also provides a simple hierarchy for Perl 5 types, here is
004222dc 826that hierarchy represented visually.
e522431d 827
828 Any
e85d2a5d 829 Item
5a4c5493 830 Bool
7e4e1ad4 831 Maybe[`a]
f65cb534 832 Undef
833 Defined
5a4c5493 834 Value
5a4c5493 835 Str
f1bbe1e1 836 Num
837 Int
fcb5b0cd 838 ClassName
839 RoleName
5a4c5493 840 Ref
2c29c0e7 841 ScalarRef[`a]
7e4e1ad4 842 ArrayRef[`a]
843 HashRef[`a]
5a4c5493 844 CodeRef
845 RegexpRef
3f7376b0 846 GlobRef
94ab1609 847 FileHandle
e85d2a5d 848 Object
e522431d 849
4ab662d6 850B<NOTE:> Any type followed by a type parameter C<[`a]> can be
7e4e1ad4 851parameterized, this means you can say:
852
757e07ef 853 ArrayRef[Int] # an array of integers
7e4e1ad4 854 HashRef[CodeRef] # a hash of str to CODE ref mappings
2c29c0e7 855 ScalarRef[Int] # a reference to an integer
7e4e1ad4 856 Maybe[Str] # value may be a string, may be undefined
857
4e8a0f64 858If Moose finds a name in brackets that it does not recognize as an
859existing type, it assumes that this is a class name, for example
860C<ArrayRef[DateTime]>.
861
e7fcb7b2 862B<NOTE:> Unless you parameterize a type, then it is invalid to include
863the square brackets. I.e. C<ArrayRef[]> will be treated as a new type
864name, I<not> as a parameterization of C<ArrayRef>.
e606ae5f 865
4ab662d6 866B<NOTE:> The C<Undef> type constraint for the most part works
867correctly now, but edge cases may still exist, please use it
6549b0d1 868sparingly.
703e92fb 869
7e4e1ad4 870B<NOTE:> The C<ClassName> type constraint does a complex package
e7fcb7b2 871existence check. This means that your class B<must> be loaded for this
872type constraint to pass.
9af1d28b 873
e7fcb7b2 874B<NOTE:> The C<RoleName> constraint checks a string is a I<package
4831e2de 875name> which is a role, like C<'MyApp::Role::Comparable'>.
ed87d4fd 876
e606ae5f 877=head2 Type Constraint Naming
004222dc 878
eee1a213 879Type name declared via this module can only contain alphanumeric
880characters, colons (:), and periods (.).
881
e606ae5f 882Since the types created by this module are global, it is suggested
883that you namespace your types just as you would namespace your
e7fcb7b2 884modules. So instead of creating a I<Color> type for your
885B<My::Graphics> module, you would call the type
886I<My::Graphics::Types::Color> instead.
004222dc 887
703e92fb 888=head2 Use with Other Constraint Modules
889
e7fcb7b2 890This module can play nicely with other constraint modules with some
891slight tweaking. The C<where> clause in types is expected to be a
69229b40 892C<CODE> reference which checks its first argument and returns a
e7fcb7b2 893boolean. Since most constraint modules work in a similar way, it
894should be simple to adapt them to work with Moose.
703e92fb 895
e85d2a5d 896For instance, this is how you could use it with
897L<Declare::Constraints::Simple> to declare a completely new type.
703e92fb 898
9e856c83 899 type 'HashOfArrayOfObjects',
04eec387 900 where {
901 IsHashRef(
902 -keys => HasLength,
903 -values => IsArrayRef(IsObject)
904 )->(@_);
905 };
703e92fb 906
2c739d1a 907For more examples see the F<t/examples/example_w_DCS.t> test
e7fcb7b2 908file.
703e92fb 909
69229b40 910Here is an example of using L<Test::Deep> and its non-test
e85d2a5d 911related C<eq_deeply> function.
703e92fb 912
04eec387 913 type 'ArrayOfHashOfBarsAndRandomNumbers',
914 where {
e85d2a5d 915 eq_deeply($_,
703e92fb 916 array_each(subhashof({
917 bar => isa('Bar'),
918 random_number => ignore()
e85d2a5d 919 })))
703e92fb 920 };
921
e606ae5f 922For a complete example see the
2c739d1a 923F<t/examples/example_w_TestDeep.t> test file.
e85d2a5d 924
32549612 925=head2 Error messages
926
927Type constraints can also specify custom error messages, for when they fail to
928validate. This is provided as just another coderef, which receives the invalid
929value in C<$_>, as in:
930
931 subtype 'PositiveInt',
932 as 'Int',
933 where { $_ > 0 },
934 message { "$_ is not a positive integer!" };
935
936If no message is specified, a default message will be used, which indicates
937which type constraint was being used and what value failed. If
938L<Devel::PartialDump> (version 0.14 or higher) is installed, it will be used to
939display the invalid value, otherwise it will just be printed as is.
940
a15dff8d 941=head1 FUNCTIONS
942
943=head2 Type Constraint Constructors
944
e7fcb7b2 945The following functions are used to create type constraints. They
946will also register the type constraints your create in a global
947registry that is used to look types up by name.
a15dff8d 948
cec39889 949See the L</SYNOPSIS> for an example of how to use these.
a15dff8d 950
6ba6d68c 951=over 4
a15dff8d 952
04eec387 953=item B<< subtype 'Name', as 'Parent', where { } ... >>
182134e8 954
e85d2a5d 955This creates a named subtype.
d6e2d9a1 956
dba9208a 957If you provide a parent that Moose does not recognize, it will
958automatically create a new class type constraint for this name.
959
9e856c83 960When creating a named type, the C<subtype> function should either be
961called with the sugar helpers (C<where>, C<message>, etc), or with a
962name and a hashref of parameters:
963
964 subtype( 'Foo', { where => ..., message => ... } );
965
966The valid hashref keys are C<as> (the parent), C<where>, C<message>,
967and C<optimize_as>.
9a63faba 968
04eec387 969=item B<< subtype as 'Parent', where { } ... >>
182134e8 970
e85d2a5d 971This creates an unnamed subtype and will return the type
972constraint meta-object, which will be an instance of
973L<Moose::Meta::TypeConstraint>.
a15dff8d 974
9e856c83 975When creating an anonymous type, the C<subtype> function should either
976be called with the sugar helpers (C<where>, C<message>, etc), or with
977just a hashref of parameters:
978
979 subtype( { where => ..., message => ... } );
980
620db045 981=item B<class_type ($class, ?$options)>
3fef8ce8 982
ed87d4fd 983Creates a new subtype of C<Object> with the name C<$class> and the
984metaclass L<Moose::Meta::TypeConstraint::Class>.
3fef8ce8 985
83aa5247 986 # Create a type called 'Box' which tests for objects which ->isa('Box')
987 class_type 'Box';
988
00954dd1 989By default, the name of the type and the name of the class are the same, but
990you can specify both separately.
83aa5247 991
992 # Create a type called 'Box' which tests for objects which ->isa('ObjectLibrary::Box');
993 class_type 'Box', { class => 'ObjectLibrary::Box' };
994
620db045 995=item B<role_type ($role, ?$options)>
996
ed87d4fd 997Creates a C<Role> type constraint with the name C<$role> and the
998metaclass L<Moose::Meta::TypeConstraint::Role>.
620db045 999
83aa5247 1000 # Create a type called 'Walks' which tests for objects which ->does('Walks')
1001 role_type 'Walks';
1002
00954dd1 1003By default, the name of the type and the name of the role are the same, but
1004you can specify both separately.
83aa5247 1005
1006 # Create a type called 'Walks' which tests for objects which ->does('MooseX::Role::Walks');
1007 role_type 'Walks', { role => 'MooseX::Role::Walks' };
1008
1b2c9bda 1009=item B<maybe_type ($type)>
1010
1011Creates a type constraint for either C<undef> or something of the
1012given type.
1013
bce5d4a5 1014=item B<duck_type ($name, \@methods)>
e451e855 1015
88b68372 1016This will create a subtype of Object and test to make sure the value
bce5d4a5 1017C<can()> do the methods in C<\@methods>.
88b68372 1018
1019This is intended as an easy way to accept non-Moose objects that
1020provide a certain interface. If you're using Moose classes, we
1021recommend that you use a C<requires>-only Role instead.
e451e855 1022
1023=item B<duck_type (\@methods)>
1024
bce5d4a5 1025If passed an ARRAY reference as the only parameter instead of the
1026C<$name>, C<\@methods> pair, this will create an unnamed duck type.
1027This can be used in an attribute definition like so:
e451e855 1028
88b68372 1029 has 'cache' => (
1030 is => 'ro',
1031 isa => duck_type( [qw( get_set )] ),
1032 );
e451e855 1033
bce5d4a5 1034=item B<enum ($name, \@values)>
fcec2383 1035
e85d2a5d 1036This will create a basic subtype for a given set of strings.
1037The resulting constraint will be a subtype of C<Str> and
bce5d4a5 1038will match any of the items in C<\@values>. It is case sensitive.
cec39889 1039See the L</SYNOPSIS> for a simple example.
2c0cbef7 1040
6549b0d1 1041B<NOTE:> This is not a true proper enum type, it is simply
1042a convenient constraint builder.
2c0cbef7 1043
9f4334a1 1044=item B<enum (\@values)>
1045
bce5d4a5 1046If passed an ARRAY reference as the only parameter instead of the
1047C<$name>, C<\@values> pair, this will create an unnamed enum. This
1048can then be used in an attribute definition like so:
9f4334a1 1049
1050 has 'sort_order' => (
1051 is => 'ro',
4ab662d6 1052 isa => enum([qw[ ascending descending ]]),
9f4334a1 1053 );
1054
74dccf76 1055=item B<union ($name, \@constraints)>
1056
1057This will create a basic subtype where any of the provided constraints
1058may match in order to satisfy this constraint.
1059
1060=item B<union (\@constraints)>
1061
1062If passed an ARRAY reference as the only parameter instead of the
1063C<$name>, C<\@constraints> pair, this will create an unnamed union.
1064This can then be used in an attribute definition like so:
1065
1066 has 'items' => (
1067 is => 'ro',
1068 isa => union([qw[ Str ArrayRef ]]),
1069 );
1070
1071This is similar to the existing string union:
1072
1073 isa => 'Str|ArrayRef'
1074
1075except that it supports anonymous elements as child constraints:
1076
1077 has 'color' => (
1078 isa => 'ro',
1079 isa => union([ 'Int', enum([qw[ red green blue ]]) ]),
1080 );
1081
e7fcb7b2 1082=item B<as 'Parent'>
a15dff8d 1083
6ba6d68c 1084This is just sugar for the type constraint construction syntax.
a15dff8d 1085
e7fcb7b2 1086It takes a single argument, which is the name of a parent type.
1087
1088=item B<where { ... }>
a15dff8d 1089
6ba6d68c 1090This is just sugar for the type constraint construction syntax.
76d37e5a 1091
e7fcb7b2 1092It takes a subroutine reference as an argument. When the type
1093constraint is tested, the reference is run with the value to be tested
1094in C<$_>. This reference should return true or false to indicate
1095whether or not the constraint check passed.
e606ae5f 1096
e7fcb7b2 1097=item B<message { ... }>
76d37e5a 1098
1099This is just sugar for the type constraint construction syntax.
a15dff8d 1100
e7fcb7b2 1101It takes a subroutine reference as an argument. When the type
1102constraint fails, then the code block is run with the value provided
1103in C<$_>. This reference should return a string, which will be used in
1104the text of the exception thrown.
e606ae5f 1105
7142d232 1106=item B<inline_as { ... }>
1107
1108This can be used to define a "hand optimized" inlinable version of your type
1109constraint.
1110
1111You provide a subroutine which will be called I<as a method> on a
1112L<Moose::Meta::TypeConstraint> object. It will receive a single parameter, the
1113name of the variable to check, typically something like C<"$_"> or C<"$_[0]">.
1114
1115The subroutine should return a code string suitable for inlining. You can
297899d1 1116assume that the check will be wrapped in parentheses when it is inlined.
7142d232 1117
01062d8a 1118The inlined code should include any checks that your type's parent types
0578d5ce 1119do. For example, the C<Value> type's inlining sub looks like this:
7142d232 1120
1121 sub {
0578d5ce 1122 'defined(' . $_[1] . ')'
1123 . ' && !ref(' . $_[1] . ')'
7142d232 1124 }
1125
0578d5ce 1126Note that it checks if the variable is defined, since it is a subtype of
1127the C<Defined> type. However, to avoid repeating code, this can be optimized as:
1128
1129 sub {
1130 $_[0]->parent()->_inline_check($_[1])
1131 . ' && !ref(' . $_[1] . ')'
1132 }
7142d232 1133
e7fcb7b2 1134=item B<optimize_as { ... }>
8ecb1fa0 1135
7142d232 1136B<This feature is deprecated, use C<inline_as> instead.>
1137
e85d2a5d 1138This can be used to define a "hand optimized" version of your
d44714be 1139type constraint which can be used to avoid traversing a subtype
6549b0d1 1140constraint hierarchy.
d44714be 1141
b0f8f0ec 1142B<NOTE:> You should only use this if you know what you are doing.
1143All the built in types use this, so your subtypes (assuming they
d44714be 1144are shallow) will not likely need to use this.
1145
04eec387 1146=item B<< type 'Name', where { } ... >>
e7fcb7b2 1147
1148This creates a base type, which has no parent.
1149
1150The C<type> function should either be called with the sugar helpers
1151(C<where>, C<message>, etc), or with a name and a hashref of
1152parameters:
1153
1154 type( 'Foo', { where => ..., message => ... } );
1155
7142d232 1156The valid hashref keys are C<where>, C<message>, and C<inlined_as>.
e7fcb7b2 1157
6ba6d68c 1158=back
a15dff8d 1159
0d29b772 1160=head2 Type Constraint Utilities
1161
1162=over 4
1163
1164=item B<< match_on_type $value => ( $type => \&action, ... ?\&default ) >>
1165
1a15f4a8 1166This is a utility function for doing simple type based dispatching similar to
2ae1457e 1167match/case in OCaml and case/of in Haskell. It is not as featureful as those
1a15f4a8 1168languages, nor does not it support any kind of automatic destructuring
1169bind. Here is a simple Perl pretty printer dispatching over the core Moose
1170types.
0d29b772 1171
1172 sub ppprint {
1173 my $x = shift;
1a15f4a8 1174 match_on_type $x => (
1175 HashRef => sub {
0d29b772 1176 my $hash = shift;
1a15f4a8 1177 '{ '
1178 . (
1179 join ", " => map { $_ . ' => ' . ppprint( $hash->{$_} ) }
1180 sort keys %$hash
1181 ) . ' }';
1182 },
1183 ArrayRef => sub {
0d29b772 1184 my $array = shift;
1a15f4a8 1185 '[ ' . ( join ", " => map { ppprint($_) } @$array ) . ' ]';
1186 },
1187 CodeRef => sub {'sub { ... }'},
1188 RegexpRef => sub { 'qr/' . $_ . '/' },
1189 GlobRef => sub { '*' . B::svref_2object($_)->NAME },
0d29b772 1190 Object => sub { $_->can('to_string') ? $_->to_string : $_ },
1a15f4a8 1191 ScalarRef => sub { '\\' . ppprint( ${$_} ) },
1192 Num => sub {$_},
1193 Str => sub { '"' . $_ . '"' },
1194 Undef => sub {'undef'},
1195 => sub { die "I don't know what $_ is" }
1196 );
0d29b772 1197 }
1198
e7597637 1199Or a simple JSON serializer:
1200
1201 sub to_json {
1202 my $x = shift;
1a15f4a8 1203 match_on_type $x => (
1204 HashRef => sub {
e7597637 1205 my $hash = shift;
1a15f4a8 1206 '{ '
1207 . (
1208 join ", " =>
1209 map { '"' . $_ . '" : ' . to_json( $hash->{$_} ) }
1210 sort keys %$hash
1211 ) . ' }';
1212 },
1213 ArrayRef => sub {
e7597637 1214 my $array = shift;
1a15f4a8 1215 '[ ' . ( join ", " => map { to_json($_) } @$array ) . ' ]';
1216 },
1217 Num => sub {$_},
1218 Str => sub { '"' . $_ . '"' },
1219 Undef => sub {'null'},
1220 => sub { die "$_ is not acceptable json type" }
1221 );
e7597637 1222 }
1223
1a15f4a8 1224The matcher is done by mapping a C<$type> to an C<\&action>. The C<$type> can
1225be either a string type or a L<Moose::Meta::TypeConstraint> object, and
1226C<\&action> is a subroutine reference. This function will dispatch on the
1227first match for C<$value>. It is possible to have a catch-all by providing an
1228additional subroutine reference as the final argument to C<match_on_type>.
0d29b772 1229
1230=back
1231
6ba6d68c 1232=head2 Type Coercion Constructors
a15dff8d 1233
e7fcb7b2 1234You can define coercions for type constraints, which allow you to
1235automatically transform values to something valid for the type
1236constraint. If you ask your accessor to coerce, then Moose will run
1237the type-coercion code first, followed by the type constraint
1238check. This feature should be used carefully as it is very powerful
1239and could easily take off a limb if you are not careful.
a15dff8d 1240
cec39889 1241See the L</SYNOPSIS> for an example of how to use these.
a15dff8d 1242
6ba6d68c 1243=over 4
a15dff8d 1244
04eec387 1245=item B<< coerce 'Name', from 'OtherName', via { ... } >>
a15dff8d 1246
e7fcb7b2 1247This defines a coercion from one type to another. The C<Name> argument
1248is the type you are coercing I<to>.
1249
f55dd47f 1250To define multiple coercions, supply more sets of from/via pairs:
1251
04eec387 1252 coerce 'Name',
1253 from 'OtherName', via { ... },
1254 from 'ThirdName', via { ... };
f55dd47f 1255
e7fcb7b2 1256=item B<from 'OtherName'>
a15dff8d 1257
6ba6d68c 1258This is just sugar for the type coercion construction syntax.
1259
e7fcb7b2 1260It takes a single type name (or type object), which is the type being
1261coerced I<from>.
1262
1263=item B<via { ... }>
a15dff8d 1264
6ba6d68c 1265This is just sugar for the type coercion construction syntax.
a15dff8d 1266
e7fcb7b2 1267It takes a subroutine reference. This reference will be called with
1268the value to be coerced in C<$_>. It is expected to return a new value
1269of the proper type for the coercion.
1270
a15dff8d 1271=back
1272
e7fcb7b2 1273=head2 Creating and Finding Type Constraints
1274
1275These are additional functions for creating and finding type
1276constraints. Most of these functions are not available for
1277importing. The ones that are importable as specified.
004222dc 1278
1279=over 4
1280
e7fcb7b2 1281=item B<find_type_constraint($type_name)>
eb4c4e82 1282
e7fcb7b2 1283This function can be used to locate the L<Moose::Meta::TypeConstraint>
1284object for a named type.
eb4c4e82 1285
e7fcb7b2 1286This function is importable.
004222dc 1287
e7fcb7b2 1288=item B<register_type_constraint($type_object)>
004222dc 1289
e7fcb7b2 1290This function will register a L<Moose::Meta::TypeConstraint> with the
1291global type registry.
004222dc 1292
e7fcb7b2 1293This function is importable.
004222dc 1294
e7fcb7b2 1295=item B<normalize_type_constraint_name($type_constraint_name)>
004222dc 1296
e7fcb7b2 1297This method takes a type constraint name and returns the normalized
1298form. This removes any whitespace in the string.
004222dc 1299
e7fcb7b2 1300=item B<create_type_constraint_union($pipe_separated_types | @type_constraint_names)>
004222dc 1301
2dae61ad 1302=item B<create_named_type_constraint_union($name, $pipe_separated_types | @type_constraint_names)>
1303
e7fcb7b2 1304This can take a union type specification like C<'Int|ArrayRef[Int]'>,
1305or a list of names. It returns a new
1306L<Moose::Meta::TypeConstraint::Union> object.
004222dc 1307
e7fcb7b2 1308=item B<create_parameterized_type_constraint($type_name)>
620db045 1309
e7fcb7b2 1310Given a C<$type_name> in the form of C<'BaseType[ContainerType]'>,
1311this will create a new L<Moose::Meta::TypeConstraint::Parameterized>
1312object. The C<BaseType> must exist already exist as a parameterizable
1313type.
620db045 1314
e7fcb7b2 1315=item B<create_class_type_constraint($class, $options)>
dabed765 1316
e7fcb7b2 1317Given a class name this function will create a new
1318L<Moose::Meta::TypeConstraint::Class> object for that class name.
004222dc 1319
e7fcb7b2 1320The C<$options> is a hash reference that will be passed to the
1321L<Moose::Meta::TypeConstraint::Class> constructor (as a hash).
620db045 1322
e7fcb7b2 1323=item B<create_role_type_constraint($role, $options)>
620db045 1324
e7fcb7b2 1325Given a role name this function will create a new
1326L<Moose::Meta::TypeConstraint::Role> object for that role name.
620db045 1327
e7fcb7b2 1328The C<$options> is a hash reference that will be passed to the
1329L<Moose::Meta::TypeConstraint::Role> constructor (as a hash).
620db045 1330
8a6c8c47 1331=item B<create_enum_type_constraint($name, $values)>
1332
1333Given a enum name this function will create a new
1334L<Moose::Meta::TypeConstraint::Enum> object for that enum name.
1335
0a6bff54 1336=item B<create_duck_type_constraint($name, $methods)>
1337
1338Given a duck type name this function will create a new
1339L<Moose::Meta::TypeConstraint::DuckType> object for that enum name.
1340
e7fcb7b2 1341=item B<find_or_parse_type_constraint($type_name)>
620db045 1342
ec4b72d2 1343Given a type name, this first attempts to find a matching constraint
e7fcb7b2 1344in the global registry.
620db045 1345
e7fcb7b2 1346If the type name is a union or parameterized type, it will create a
1347new object of the appropriate, but if given a "regular" type that does
1348not yet exist, it simply returns false.
620db045 1349
e7fcb7b2 1350When given a union or parameterized type, the member or base type must
1351already exist.
620db045 1352
e7fcb7b2 1353If it creates a new union or parameterized type, it will add it to the
1354global registry.
004222dc 1355
e7fcb7b2 1356=item B<find_or_create_isa_type_constraint($type_name)>
004222dc 1357
e7fcb7b2 1358=item B<find_or_create_does_type_constraint($type_name)>
004222dc 1359
e7fcb7b2 1360These functions will first call C<find_or_parse_type_constraint>. If
72042ad7 1361that function does not return a type, a new type object will
e7fcb7b2 1362be created.
004222dc 1363
e7fcb7b2 1364The C<isa> variant will use C<create_class_type_constraint> and the
1365C<does> variant will use C<create_role_type_constraint>.
004222dc 1366
1367=item B<get_type_constraint_registry>
1368
e7fcb7b2 1369Returns the L<Moose::Meta::TypeConstraint::Registry> object which
004222dc 1370keeps track of all type constraints.
1371
1372=item B<list_all_type_constraints>
1373
e7fcb7b2 1374This will return a list of type constraint names in the global
1375registry. You can then fetch the actual type object using
1376C<find_type_constraint($type_name)>.
004222dc 1377
1378=item B<list_all_builtin_type_constraints>
1379
e7fcb7b2 1380This will return a list of builtin type constraints, meaning those
1381which are defined in this module. See the L<Default Type Constraints>
1382section for a complete list.
004222dc 1383
1384=item B<export_type_constraints_as_functions>
1385
e7fcb7b2 1386This will export all the current type constraints as functions into
1387the caller's namespace (C<Int()>, C<Str()>, etc). Right now, this is
1388mostly used for testing, but it might prove useful to others.
004222dc 1389
1390=item B<get_all_parameterizable_types>
1391
e7fcb7b2 1392This returns all the parameterizable types that have been registered,
1393as a list of type objects.
004222dc 1394
e7fcb7b2 1395=item B<add_parameterizable_type($type)>
004222dc 1396
1397Adds C<$type> to the list of parameterizable types
1398
1399=back
1400
a15dff8d 1401=head1 BUGS
1402
d4048ef3 1403See L<Moose/BUGS> for details on reporting bugs.
a15dff8d 1404
81dc201f 1405=cut