File Coverage

blib/lib/Type/Coercion.pm
Criterion Covered Total %
statement 253 254 99.2
branch 95 120 79.1
condition 67 101 66.3
subroutine 60 61 98.3
pod 34 34 100.0
total 509 570 89.1


line stmt bran cond sub pod time code
1             package Type::Coercion;
2              
3 288     288   9107 use 5.008001;
  288         1034  
4 288     288   1677 use strict;
  288         629  
  288         6813  
5 288     288   1572 use warnings;
  288         688  
  288         13909  
6              
7             BEGIN {
8 288     288   1225 $Type::Coercion::AUTHORITY = 'cpan:TOBYINK';
9 288         12154 $Type::Coercion::VERSION = '2.003_000';
10             }
11              
12             $Type::Coercion::VERSION =~ tr/_//d;
13              
14 288     288   3082 use Eval::TypeTiny qw<>;
  288         1772  
  288         7727  
15 288     288   1893 use Scalar::Util qw< blessed >;
  288         781  
  288         16373  
16 288     288   2070 use Types::TypeTiny qw<>;
  288         720  
  288         1110435  
17              
18 6     6   38 sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }
  6         33  
19              
20             require Type::Tiny;
21              
22             __PACKAGE__->Type::Tiny::_install_overloads(
23             q("") => sub {
24 719 50   719   10049 caller =~ m{^(Moo::HandleMoose|Sub::Quote)}
25             ? $_[0]->_stringify_no_magic
26             : $_[0]->display_name;
27             },
28 61528     61528   217426 q(bool) => sub { 1 },
29             q(&{}) => "_overload_coderef",
30             );
31              
32             __PACKAGE__->Type::Tiny::_install_overloads(
33 2     2   20 q(~~) => sub { $_[0]->has_coercion_for_value( $_[1] ) },
34             ) if Type::Tiny::SUPPORT_SMARTMATCH();
35              
36             sub _overload_coderef {
37 17     17   35 my $self = shift;
38            
39 17 100 100     176 if ( "Sub::Quote"->can( "quote_sub" ) && $self->can_be_inlined ) {
40             $self->{_overload_coderef} =
41             Sub::Quote::quote_sub( $self->inline_coercion( '$_[0]' ) )
42 3 50 66     27 if !$self->{_overload_coderef} || !$self->{_sub_quoted}++;
43             }
44             else {
45 14         69 Scalar::Util::weaken( my $weak = $self );
46 14   100 29   90 $self->{_overload_coderef} ||= sub { $weak->coerce( @_ ) };
  29         7264  
47             }
48            
49 17         389 $self->{_overload_coderef};
50             } #/ sub _overload_coderef
51              
52             sub new {
53 13504     13504 1 25345 my $class = shift;
54 13504 100       41161 my %params = ( @_ == 1 ) ? %{ $_[0] } : @_;
  846         4276  
55            
56 13504 100       34708 $params{name} = '__ANON__' unless exists( $params{name} );
57 13504   100     46347 my $C = delete( $params{type_coercion_map} ) || [];
58 13504         20922 my $F = delete( $params{frozen} );
59            
60 13504         23642 my $self = bless \%params, $class;
61 13504 100       27006 $self->add_type_coercions( @$C ) if @$C;
62 13504         30160 $self->_preserve_type_constraint;
63 13504         45181 Scalar::Util::weaken( $self->{type_constraint} ); # break ref cycle
64 13504 100       23546 $self->{frozen} = $F if $F;
65            
66 13504 100       24018 unless ( $self->is_anon ) {
67            
68             # First try a fast ASCII-only expression, but fall back to Unicode
69 892 50 33     2096 $self->name =~ /^_{0,2}[A-Z][A-Za-z0-9_]+$/sm
70             or eval q( use 5.008; $self->name =~ /^_{0,2}\p{Lu}[\p{L}0-9_]+$/sm )
71             or _croak '"%s" is not a valid coercion name', $self->name;
72             }
73            
74 13504         32697 return $self;
75             } #/ sub new
76              
77             sub _stringify_no_magic {
78 1     1   21 sprintf(
79             '%s=%s(0x%08x)', blessed( $_[0] ), Scalar::Util::reftype( $_[0] ),
80             Scalar::Util::refaddr( $_[0] )
81             );
82             }
83              
84 17637     17637 1 54446 sub name { $_[0]{name} }
85 719   66 719 1 6096 sub display_name { $_[0]{display_name} ||= $_[0]->_build_display_name }
86 43     43 1 134 sub library { $_[0]{library} }
87              
88             sub type_constraint {
89 5365   100 5365 1 14248 $_[0]{type_constraint} ||= $_[0]->_maybe_restore_type_constraint;
90             }
91 23861   100 23861 1 145333 sub type_coercion_map { $_[0]{type_coercion_map} ||= [] }
92 27   100 27 1 299 sub moose_coercion { $_[0]{moose_coercion} ||= $_[0]->_build_moose_coercion }
93              
94             sub compiled_coercion {
95 1609   66 1609 1 8251 $_[0]{compiled_coercion} ||= $_[0]->_build_compiled_coercion;
96             }
97 4334   100 4334 1 18799 sub frozen { $_[0]{frozen} ||= 0 }
98 16     16 1 71 sub coercion_generator { $_[0]{coercion_generator} }
99 8     8 1 123 sub parameters { $_[0]{parameters} }
100 8     8 1 17 sub parameterized_from { $_[0]{parameterized_from} }
101              
102 1012     1012 1 6437 sub has_library { exists $_[0]{library} }
103 2625     2625 1 5625 sub has_type_constraint { defined $_[0]->type_constraint } # sic
104 1020     1020 1 6005 sub has_coercion_generator { exists $_[0]{coercion_generator} }
105 25     25 1 143 sub has_parameters { exists $_[0]{parameters} }
106              
107             sub _preserve_type_constraint {
108 13430     13430   18468 my $self = shift;
109             $self->{_compiled_type_constraint_check} =
110             $self->{type_constraint}->compiled_check
111 13430 100       49053 if $self->{type_constraint};
112             }
113              
114             sub _maybe_restore_type_constraint {
115 6     6   12 my $self = shift;
116 6 100       21 if ( my $check = $self->{_compiled_type_constraint_check} ) {
117 1         4 return Type::Tiny->new( constraint => $check );
118             }
119 5         26 return; # uncoverable statement
120             }
121              
122             sub add {
123 2     2 1 678 my $class = shift;
124 2         6 my ( $x, $y, $swap ) = @_;
125            
126 2 50       45 Types::TypeTiny::is_TypeTiny( $x ) and return $x->plus_fallback_coercions( $y );
127 2 50       29 Types::TypeTiny::is_TypeTiny( $y ) and return $y->plus_coercions( $x );
128            
129 2 50 33     20 _croak "Attempt to add $class to something that is not a $class"
      33        
      33        
130             unless blessed( $x )
131             && blessed( $y )
132             && $x->isa( $class )
133             && $y->isa( $class );
134            
135 2 50       8 ( $y, $x ) = ( $x, $y ) if $swap;
136            
137 2         3 my %opts;
138 2 50 33     5 if ( $x->has_type_constraint
    0 33        
      0        
139             and $y->has_type_constraint
140             and $x->type_constraint == $y->type_constraint )
141             {
142 2         5 $opts{type_constraint} = $x->type_constraint;
143             }
144             elsif ( $x->has_type_constraint and $y->has_type_constraint ) {
145            
146             # require Type::Tiny::Union;
147             # $opts{type_constraint} = "Type::Tiny::Union"->new(
148             # type_constraints => [ $x->type_constraint, $y->type_constraint ],
149             # );
150             }
151 2   33     11 $opts{display_name} ||= "$x+$y";
152 2 50       20 delete $opts{display_name} if $opts{display_name} eq '__ANON__+__ANON__';
153            
154 2         14 my $new = $class->new( %opts );
155 2         4 $new->add_type_coercions( @{ $x->type_coercion_map } );
  2         6  
156 2         4 $new->add_type_coercions( @{ $y->type_coercion_map } );
  2         4  
157 2         9 return $new;
158             } #/ sub add
159              
160             sub _build_display_name {
161 117     117   352 shift->name;
162             }
163              
164             sub qualified_name {
165 1012     1012 1 1745 my $self = shift;
166            
167 1012 100 66     2765 if ( $self->has_library and not $self->is_anon ) {
168 43         171 return sprintf( "%s::%s", $self->library, $self->name );
169             }
170            
171 969         2500 return $self->name;
172             }
173              
174             sub is_anon {
175 14603     14603 1 19834 my $self = shift;
176 14603         24084 $self->name eq "__ANON__";
177             }
178              
179             sub _clear_compiled_coercion {
180 1276     1276   2599 delete $_[0]{_overload_coderef};
181 1276         2489 delete $_[0]{compiled_coercion};
182             }
183              
184 13406     13406 1 23085 sub freeze { $_[0]{frozen} = 1; $_[0] }
  13406         22482  
185 1     1 1 4 sub i_really_want_to_unfreeze { $_[0]{frozen} = 0; $_[0] }
  1         2  
186              
187             sub coerce {
188 721     721 1 4178 my $self = shift;
189 721         1708 return $self->compiled_coercion->( @_ );
190             }
191              
192             sub assert_coerce {
193 64     64 1 108 my $self = shift;
194 64         134 my $r = $self->coerce( @_ );
195 64 50       819 $self->type_constraint->assert_valid( $r )
196             if $self->has_type_constraint;
197 63         202 return $r;
198             }
199              
200             sub has_coercion_for_type {
201 17     17 1 150 my $self = shift;
202 17         56 my $type = Types::TypeTiny::to_TypeTiny( $_[0] );
203            
204 17 100 100     63 return "0 but true"
205             if $self->has_type_constraint
206             && $type->is_a_type_of( $self->type_constraint );
207            
208 15         57 my $c = $self->type_coercion_map;
209 15         69 for ( my $i = 0 ; $i <= $#$c ; $i += 2 ) {
210 19 100       68 return !!1 if $type->is_a_type_of( $c->[$i] );
211             }
212 4         26 return;
213             } #/ sub has_coercion_for_type
214              
215             sub has_coercion_for_value {
216 6     6 1 14 my $self = shift;
217 6         10 local $_ = $_[0];
218            
219 6 100 66     14 return "0 but true"
220             if $self->has_type_constraint
221             && $self->type_constraint->check( @_ );
222            
223 5         35 my $c = $self->type_coercion_map;
224 5         18 for ( my $i = 0 ; $i <= $#$c ; $i += 2 ) {
225 7 100       31 return !!1 if $c->[$i]->check( @_ );
226             }
227 2         16 return;
228             } #/ sub has_coercion_for_value
229              
230             sub add_type_coercions {
231 1280     1280 1 3037 my $self = shift;
232 1280         3614 my @args = @_;
233            
234 1280 100       3471 _croak "Attempt to add coercion code to a Type::Coercion which has been frozen"
235             if $self->frozen;
236            
237 1276         3675 while ( @args ) {
238 1904         6675 my $type = Types::TypeTiny::to_TypeTiny( shift @args );
239            
240 1904 100 66     10581 if ( blessed $type and my $method = $type->can( 'type_coercion_map' ) ) {
241 1         10 push @{ $self->type_coercion_map }, @{ $method->( $type ) };
  1         5  
  1         4  
242             }
243             else {
244 1903         3688 my $coercion = shift @args;
245 1903 50       45832 _croak "Types must be blessed Type::Tiny objects"
246             unless Types::TypeTiny::is_TypeTiny( $type );
247 1903 50 66     15000 _croak "Coercions must be code references or strings"
248             unless Types::TypeTiny::is_StringLike( $coercion )
249             || Types::TypeTiny::is_CodeLike( $coercion );
250 1903         3122 push @{ $self->type_coercion_map }, $type, $coercion;
  1903         4641  
251             }
252             } #/ while ( @args )
253            
254 1276         4887 $self->_clear_compiled_coercion;
255 1276         2874 return $self;
256             } #/ sub add_type_coercions
257              
258             sub _build_compiled_coercion {
259 682     682   1577 my $self = shift;
260            
261 682         1313 my @mishmash = @{ $self->type_coercion_map };
  682         1821  
262 1     1   6 return sub { $_[0] }
263 682 100       2464 unless @mishmash;
264            
265 681 100       2553 if ( $self->can_be_inlined ) {
266 540         2735 return Eval::TypeTiny::eval_closure(
267             source => sprintf( 'sub ($) { %s }', $self->inline_coercion( '$_[0]' ) ),
268             description => sprintf( "compiled coercion '%s'", $self ),
269             );
270             }
271            
272             # These arrays will be closed over.
273 141         413 my ( @types, @codes );
274 141         501 while ( @mishmash ) {
275 178         423 push @types, shift @mishmash;
276 178         541 push @codes, shift @mishmash;
277             }
278 141 50       410 if ( $self->has_type_constraint ) {
279 141         524 unshift @types, $self->type_constraint;
280 141         904 unshift @codes, undef;
281             }
282            
283 141         650 my @sub;
284            
285 141         584 for my $i ( 0 .. $#types ) {
286 319 100       927 push @sub,
287             $types[$i]->can_be_inlined
288             ? sprintf( 'if (%s)', $types[$i]->inline_check( '$_[0]' ) )
289             : sprintf( 'if ($checks[%d]->(@_))', $i );
290 319 100       2261 push @sub,
    100          
291             !defined( $codes[$i] )
292             ? sprintf( ' { return $_[0] }' )
293             : Types::TypeTiny::is_StringLike( $codes[$i] ) ? sprintf(
294             ' { local $_ = $_[0]; return scalar(%s); }',
295             $codes[$i]
296             )
297             : sprintf( ' { local $_ = $_[0]; return scalar($codes[%d]->(@_)) }', $i );
298             } #/ for my $i ( 0 .. $#types)
299            
300 141         421 push @sub, 'return $_[0];';
301            
302 141         1022 return Eval::TypeTiny::eval_closure(
303             source => sprintf( 'sub ($) { %s }', join qq[\n], @sub ),
304             description => sprintf( "compiled coercion '%s'", $self ),
305             environment => {
306             '@checks' => [ map $_->compiled_check, @types ],
307             '@codes' => \@codes,
308             },
309             );
310             } #/ sub _build_compiled_coercion
311              
312             sub can_be_inlined {
313 1681     1681 1 2810 my $self = shift;
314            
315 1681 100       11652 return unless $self->frozen;
316            
317             return
318 1622 100 66     4145 if $self->has_type_constraint
319             && !$self->type_constraint->can_be_inlined;
320            
321 1540         4665 my @mishmash = @{ $self->type_coercion_map };
  1540         3420  
322 1540         5696 while ( @mishmash ) {
323 1570         4350 my ( $type, $converter ) = splice( @mishmash, 0, 2 );
324 1570 100       4377 return unless $type->can_be_inlined;
325 1568 100       7638 return unless Types::TypeTiny::is_StringLike( $converter );
326             }
327 1397         5176 return !!1;
328             } #/ sub can_be_inlined
329              
330             sub _source_type_union {
331 64     64   142 my $self = shift;
332            
333 64         123 my @r;
334 64 50       196 push @r, $self->type_constraint if $self->has_type_constraint;
335            
336 64         144 my @mishmash = @{ $self->type_coercion_map };
  64         165  
337 64         226 while ( @mishmash ) {
338 65         226 my ( $type ) = splice( @mishmash, 0, 2 );
339 65         227 push @r, $type;
340             }
341            
342 64         11170 require Type::Tiny::Union;
343 64         459 return "Type::Tiny::Union"->new( type_constraints => \@r, tmp => 1 );
344             } #/ sub _source_type_union
345              
346             sub inline_coercion {
347 689     689 1 1452 my $self = shift;
348 689         1624 my $varname = $_[0];
349            
350 689 50       3763 _croak "This coercion cannot be inlined" unless $self->can_be_inlined;
351            
352 689         1681 my @mishmash = @{ $self->type_coercion_map };
  689         3168  
353 689 50       2325 return "($varname)" unless @mishmash;
354            
355 689         1519 my ( @types, @codes );
356 689         3635 while ( @mishmash ) {
357 706         1673 push @types, shift @mishmash;
358 706         3372 push @codes, shift @mishmash;
359             }
360 689 50       1892 if ( $self->has_type_constraint ) {
361 689         2064 unshift @types, $self->type_constraint;
362 689         1886 unshift @codes, undef;
363             }
364            
365 689         1513 my @sub;
366            
367 689         4269 for my $i ( 0 .. $#types ) {
368 1395         4622 push @sub, sprintf( '(%s) ?', $types[$i]->inline_check( $varname ) );
369 1395 100 100     12843 push @sub,
    100          
370             ( defined( $codes[$i] ) && ( $varname eq '$_' ) )
371             ? sprintf( 'scalar(do { %s }) :', $codes[$i] )
372             : defined( $codes[$i] ) ? sprintf(
373             'scalar(do { local $_ = %s; %s }) :', $varname,
374             $codes[$i]
375             )
376             : sprintf( '%s :', $varname );
377             } #/ for my $i ( 0 .. $#types)
378            
379 689         5981 push @sub, "$varname";
380            
381 689         6822 "@sub";
382             } #/ sub inline_coercion
383              
384             sub _build_moose_coercion {
385 18     18   38 my $self = shift;
386            
387 18         51 my %options = ();
388             $options{type_coercion_map} =
389 18         51 [ $self->freeze->_codelike_type_coercion_map( 'moose_type' ) ];
390 17 100       71 $options{type_constraint} = $self->type_constraint
391             if $self->has_type_constraint;
392            
393 17         113 require Moose::Meta::TypeCoercion;
394 17         182 my $r = "Moose::Meta::TypeCoercion"->new( %options );
395            
396 17         11714 return $r;
397             } #/ sub _build_moose_coercion
398              
399             sub _codelike_type_coercion_map {
400 18     18   33 my $self = shift;
401 18         36 my $modifier = $_[0];
402            
403 18         30 my @orig = @{ $self->type_coercion_map };
  18         51  
404 17         33 my @new;
405            
406 17         90 while ( @orig ) {
407 22         79 my ( $type, $converter ) = splice( @orig, 0, 2 );
408            
409 22 50       101 push @new, $modifier ? $type->$modifier : $type;
410            
411 22 100       206 if ( Types::TypeTiny::is_CodeLike( $converter ) ) {
412 13         42 push @new, $converter;
413             }
414             else {
415 9         63 push @new, Eval::TypeTiny::eval_closure(
416             source => sprintf( 'sub { local $_ = $_[0]; %s }', $converter ),
417             description => sprintf( "temporary compiled converter from '%s'", $type ),
418             );
419             }
420             } #/ while ( @orig )
421            
422 17         84 return @new;
423             } #/ sub _codelike_type_coercion_map
424              
425             sub is_parameterizable {
426 1020     1020 1 5142 shift->has_coercion_generator;
427             }
428              
429             sub is_parameterized {
430 25     25 1 65 shift->has_parameters;
431             }
432              
433             sub parameterize {
434 8     8 1 4392 my $self = shift;
435 8 50       27 return $self unless @_;
436 8 50       28 $self->is_parameterizable
437             or _croak "Constraint '%s' does not accept parameters", "$self";
438            
439 8         40 @_ = map Types::TypeTiny::to_TypeTiny( $_ ), @_;
440            
441 8         36 return ref( $self )->new(
442             type_constraint => $self->type_constraint,
443             type_coercion_map =>
444             [ $self->coercion_generator->( $self, $self->type_constraint, @_ ) ],
445             parameters => \@_,
446             frozen => 1,
447             parameterized_from => $self,
448             );
449             } #/ sub parameterize
450              
451             sub _reparameterize {
452 8     8   22 my $self = shift;
453 8         53 my ( $target_type ) = @_;
454            
455 8 50       21 $self->is_parameterized or return $self;
456 8         28 my $parent = $self->parameterized_from;
457            
458             return ref( $self )->new(
459             type_constraint => $target_type,
460             type_coercion_map => [
461 8         22 $parent->coercion_generator->( $parent, $target_type, @{ $self->parameters } )
  8         30  
462             ],
463             parameters => \@_,
464             frozen => 1,
465             parameterized_from => $parent,
466             );
467             } #/ sub _reparameterize
468              
469             sub isa {
470 41     41 1 904 my $self = shift;
471            
472 41 100 66     165 if ( $INC{"Moose.pm"}
      100        
473             and blessed( $self )
474             and $_[0] eq 'Moose::Meta::TypeCoercion' )
475             {
476 2         20 return !!1;
477             }
478            
479 39 100 66     136 if ( $INC{"Moose.pm"}
      100        
480             and blessed( $self )
481             and $_[0] =~ /^(Class::MOP|MooseX?)::/ )
482             {
483 1         8 my $r = $self->moose_coercion->isa( @_ );
484 1 50       7 return $r if $r;
485             }
486            
487 38         281 $self->SUPER::isa( @_ );
488             } #/ sub isa
489              
490             sub can {
491 24     24 1 2831 my $self = shift;
492            
493 24         119 my $can = $self->SUPER::can( @_ );
494 24 100       133 return $can if $can;
495            
496 4 100 66     35 if ( $INC{"Moose.pm"}
      100        
497             and blessed( $self )
498             and my $method = $self->moose_coercion->can( @_ ) )
499             {
500 2     0   17 return sub { $method->( shift->moose_coercion, @_ ) };
  0         0  
501             }
502            
503 2         13 return;
504             } #/ sub can
505              
506             sub AUTOLOAD {
507 706     706   7518 my $self = shift;
508 706         4766 my ( $m ) = ( our $AUTOLOAD =~ /::(\w+)$/ );
509 706 100       23467 return if $m eq 'DESTROY';
510            
511 2 100 33     31 if ( $INC{"Moose.pm"}
      66        
512             and blessed( $self )
513             and my $method = $self->moose_coercion->can( $m ) )
514             {
515 1         4 return $method->( $self->moose_coercion, @_ );
516             }
517            
518 1   33     7 _croak q[Can't locate object method "%s" via package "%s"], $m,
519             ref( $self ) || $self;
520             } #/ sub AUTOLOAD
521              
522             # Private Moose method, but Moo uses this...
523             sub _compiled_type_coercion {
524 42     42   87 my $self = shift;
525 42 100       129 if ( @_ ) {
526 2         2 my $thing = $_[0];
527 2 100 66     25 if ( blessed( $thing ) and $thing->isa( "Type::Coercion" ) ) {
    50          
528 1         2 $self->add_type_coercions( @{ $thing->type_coercion_map } );
  1         2  
529             }
530             elsif ( Types::TypeTiny::is_CodeLike( $thing ) ) {
531 1         13 require Types::Standard;
532 1         4 $self->add_type_coercions( Types::Standard::Any(), $thing );
533             }
534             } #/ if ( @_ )
535 42         118 $self->compiled_coercion;
536             } #/ sub _compiled_type_coercion
537              
538             *compile_type_coercion = \&compiled_coercion;
539 1     1 1 5 sub meta { _croak( "Not really a Moose::Meta::TypeCoercion. Sorry!" ) }
540              
541             1;
542              
543             __END__
544              
545             =pod
546              
547             =encoding utf-8
548              
549             =head1 NAME
550              
551             Type::Coercion - a set of coercions to a particular target type constraint
552              
553             =head1 STATUS
554              
555             This module is covered by the
556             L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.
557              
558             =head1 DESCRIPTION
559              
560             =head2 Constructors
561              
562             =over
563              
564             =item C<< new(%attributes) >>
565              
566             Moose-style constructor function.
567              
568             =item C<< add($c1, $c2) >>
569              
570             Create a Type::Coercion from two existing Type::Coercion objects.
571              
572             =back
573              
574             =head2 Attributes
575              
576             Attributes are named values that may be passed to the constructor. For
577             each attribute, there is a corresponding reader method. For example:
578              
579             my $c = Type::Coercion->new( type_constraint => Int );
580             my $t = $c->type_constraint; # Int
581              
582             =head3 Important attributes
583              
584             These are the attributes you are likely to be most interested in
585             providing when creating your own type coercions, and most interested
586             in reading when dealing with coercion objects.
587              
588             =over
589              
590             =item C<type_constraint>
591              
592             Weak reference to the target type constraint (i.e. the type constraint which
593             the output of coercion coderefs is expected to conform to).
594              
595             =item C<type_coercion_map>
596              
597             Arrayref of source-type/code pairs.
598              
599             =item C<frozen>
600              
601             Boolean; default false. A frozen coercion cannot have C<add_type_coercions>
602             called upon it.
603              
604             =item C<name>
605              
606             A name for the coercion. These need to conform to certain naming
607             rules (they must begin with an uppercase letter and continue using only
608             letters, digits 0-9 and underscores).
609              
610             Optional; if not supplied will be an anonymous coercion.
611              
612             =item C<display_name>
613              
614             A name to display for the coercion when stringified. These don't have
615             to conform to any naming rules. Optional; a default name will be
616             calculated from the C<name>.
617              
618             =item C<library>
619              
620             The package name of the type library this coercion is associated with.
621             Optional. Informational only: setting this attribute does not install
622             the coercion into the package.
623              
624             =back
625              
626             =head3 Attributes related to parameterizable and parameterized coercions
627              
628             The following attributes are used for parameterized coercions, but are not
629             fully documented because they may change in the near future:
630              
631             =over
632              
633             =item C<< coercion_generator >>
634              
635             =item C<< parameters >>
636              
637             =item C<< parameterized_from >>
638              
639             =back
640              
641             =head3 Lazy generated attributes
642              
643             The following attributes should not be usually passed to the constructor;
644             unless you're doing something especially unusual, you should rely on the
645             default lazily-built return values.
646              
647             =over
648              
649             =item C<< compiled_coercion >>
650              
651             Coderef to coerce a value (C<< $_[0] >>).
652              
653             The general point of this attribute is that you should not set it, but
654             rely on the lazily-built default. Type::Coerce will usually generate a
655             pretty fast coderef, inlining all type constraint checks, etc.
656              
657             =item C<moose_coercion>
658              
659             A L<Moose::Meta::TypeCoercion> object equivalent to this one. Don't set this
660             manually; rely on the default built one.
661              
662             =back
663              
664             =head2 Methods
665              
666             =head3 Predicate methods
667              
668             These methods return booleans indicating information about the coercion.
669             They are each tightly associated with a particular attribute.
670             (See L</"Attributes">.)
671              
672             =over
673              
674             =item C<has_type_constraint>, C<has_library>
675              
676             Simple Moose-style predicate methods indicating the presence or
677             absence of an attribute.
678              
679             =item C<is_anon>
680              
681             Returns true iff the coercion does not have a C<name>.
682              
683             =back
684              
685             The following predicates are used for parameterized coercions, but are not
686             fully documented because they may change in the near future:
687              
688             =over
689              
690             =item C<< has_coercion_generator >>
691              
692             =item C<< has_parameters >>
693              
694             =item C<< is_parameterizable >>
695              
696             =item C<< is_parameterized >>
697              
698             =back
699              
700             =head3 Coercion
701              
702             The following methods are used for coercing values to a type constraint:
703              
704             =over
705              
706             =item C<< coerce($value) >>
707              
708             Coerce the value to the target type.
709              
710             Returns the coerced value, or the original value if no coercion was
711             possible.
712              
713             =item C<< assert_coerce($value) >>
714              
715             Coerce the value to the target type, and throw an exception if the result
716             does not validate against the target type constraint.
717              
718             Returns the coerced value.
719              
720             =back
721              
722             =head3 Coercion code definition methods
723              
724             These methods all return C<< $self >> so are suitable for chaining.
725              
726             =over
727              
728             =item C<< add_type_coercions($type1, $code1, ...) >>
729              
730             Takes one or more pairs of L<Type::Tiny> constraints and coercion code,
731             creating an ordered list of source types and coercion codes.
732              
733             Coercion codes can be expressed as either a string of Perl code (this
734             includes objects which overload stringification), or a coderef (or object
735             that overloads coderefification). In either case, the value to be coerced
736             is C<< $_ >>.
737              
738             C<< add_type_coercions($coercion_object) >> also works, and can be used
739             to copy coercions from another type constraint:
740              
741             $type->coercion->add_type_coercions($othertype->coercion)->freeze;
742              
743             =item C<< freeze >>
744              
745             Sets the C<frozen> attribute to true. Called automatically by L<Type::Tiny>
746             sometimes.
747              
748             =item C<< i_really_want_to_unfreeze >>
749              
750             If you really want to unfreeze a coercion, call this method.
751              
752             Don't call this method. It will potentially lead to subtle bugs.
753              
754             This method is considered unstable; future versions of Type::Tiny may
755             alter its behaviour (e.g. to throw an exception if it has been detected
756             that unfreezing this particular coercion will cause bugs).
757              
758             =back
759              
760             =head3 Parameterization
761              
762             The following method is used for parameterized coercions, but is not
763             fully documented because it may change in the near future:
764              
765             =over
766              
767             =item C<< parameterize(@params) >>
768              
769             =back
770              
771             =head3 Type coercion introspection methods
772              
773             These methods allow you to determine a coercion's relationship to type
774             constraints:
775              
776             =over
777              
778             =item C<< has_coercion_for_type($source_type) >>
779              
780             Returns true iff this coercion has a coercion from the source type.
781              
782             Returns the special string C<< "0 but true" >> if no coercion should
783             actually be necessary for this type. (For example, if a coercion coerces
784             to a theoretical "Number" type, there is probably no coercion necessary
785             for values that already conform to the "Integer" type.)
786              
787             =item C<< has_coercion_for_value($value) >>
788              
789             Returns true iff the value could be coerced by this coercion.
790              
791             Returns the special string C<< "0 but true" >> if no coercion would be
792             actually be necessary for this value (due to it already meeting the target
793             type constraint).
794              
795             =back
796              
797             The C<type_constraint> attribute provides a type constraint object for the
798             target type constraint of the coercion. See L</"Attributes">.
799              
800             =head3 Inlining methods
801              
802             =for stopwords uated
803              
804             The following methods are used to generate strings of Perl code which
805             may be pasted into stringy C<eval>uated subs to perform type coercions:
806              
807             =over
808              
809             =item C<< can_be_inlined >>
810              
811             Returns true iff the coercion can be inlined.
812              
813             =item C<< inline_coercion($varname) >>
814              
815             Much like C<inline_coerce> from L<Type::Tiny>.
816              
817             =back
818              
819             =head3 Other methods
820              
821             =over
822              
823             =item C<< qualified_name >>
824              
825             For non-anonymous coercions that have a library, returns a qualified
826             C<< "MyLib::MyCoercion" >> sort of name. Otherwise, returns the same
827             as C<name>.
828              
829             =item C<< isa($class) >>, C<< can($method) >>, C<< AUTOLOAD(@args) >>
830              
831             If Moose is loaded, then the combination of these methods is used to mock
832             a Moose::Meta::TypeCoercion.
833              
834             =back
835              
836             The following methods exist for Moose/Mouse compatibility, but do not do
837             anything useful.
838              
839             =over
840              
841             =item C<< compile_type_coercion >>
842              
843             =item C<< meta >>
844              
845             =back
846              
847             =head2 Overloading
848              
849             =over
850              
851             =item *
852              
853             Boolification is overloaded to always return true.
854              
855             =item *
856              
857             Coderefification is overloaded to call C<coerce>.
858              
859             =item *
860              
861             On Perl 5.10.1 and above, smart match is overloaded to call C<has_coercion_for_value>.
862              
863             =back
864              
865             Previous versions of Type::Coercion would overload the C<< + >> operator
866             to call C<add>. Support for this was dropped after 0.040.
867              
868             =head1 DIAGNOSTICS
869              
870             =over
871              
872             =item I<< Attempt to add coercion code to a Type::Coercion which has been frozen >>
873              
874             Type::Tiny type constraints are designed as immutable objects. Once you've
875             created a constraint, rather than modifying it you generally create child
876             constraints to do what you need.
877              
878             Type::Coercion objects, on the other hand, are mutable. Coercion routines
879             can be added at any time during the object's lifetime.
880              
881             Sometimes Type::Tiny needs to freeze a Type::Coercion object to prevent this.
882             In L<Moose> and L<Mouse> code this is likely to happen as soon as you use a
883             type constraint in an attribute.
884              
885             Workarounds:
886              
887             =over
888              
889             =item *
890              
891             Define as many of your coercions as possible within type libraries, not
892             within the code that uses the type libraries. The type library will be
893             evaluated relatively early, likely before there is any reason to freeze
894             a coercion.
895              
896             =item *
897              
898             If you do need to add coercions to a type within application code outside
899             the type library, instead create a subtype and add coercions to that. The
900             C<plus_coercions> method provided by L<Type::Tiny> should make this simple.
901              
902             =back
903              
904             =back
905              
906             =head1 BUGS
907              
908             Please report any bugs to
909             L<https://github.com/tobyink/p5-type-tiny/issues>.
910              
911             =head1 SEE ALSO
912              
913             L<Type::Tiny::Manual>.
914              
915             L<Type::Tiny>, L<Type::Library>, L<Type::Utils>, L<Types::Standard>.
916              
917             L<Type::Coercion::Union>.
918              
919             L<Moose::Meta::TypeCoercion>.
920              
921             =head1 AUTHOR
922              
923             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
924              
925             =head1 COPYRIGHT AND LICENCE
926              
927             This software is copyright (c) 2013-2014, 2017-2023 by Toby Inkster.
928              
929             This is free software; you can redistribute it and/or modify it under
930             the same terms as the Perl 5 programming language system itself.
931              
932             =head1 DISCLAIMER OF WARRANTIES
933              
934             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
935             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
936             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.