File Coverage

blib/lib/Type/Tiny.pm
Criterion Covered Total %
statement 705 769 91.9
branch 369 482 76.5
condition 212 316 67.0
subroutine 211 226 93.3
pod 86 87 98.8
total 1583 1880 84.3


line stmt bran cond sub pod time code
1             package Type::Tiny;
2              
3 310     310   1053580 use 5.008001;
  310         1166  
4 310     310   1815 use strict;
  310         5231  
  310         15141  
5 310     310   3785 use warnings;
  310         4804  
  310         44328  
6              
7             BEGIN {
8 310 50   310   24913 if ( $] < 5.010 ) { require Devel::TypeTiny::Perl58Compat }
  0         0  
9             }
10              
11             BEGIN {
12 310     310   5440 $Type::Tiny::AUTHORITY = 'cpan:TOBYINK';
13 310         630 $Type::Tiny::VERSION = '2.010001';
14 310         54157 $Type::Tiny::XS_VERSION = '0.016';
15             }
16              
17             $Type::Tiny::VERSION =~ tr/_//d;
18             $Type::Tiny::XS_VERSION =~ tr/_//d;
19              
20             our @InternalPackages = qw(
21             Devel::TypeTiny::Perl56Compat
22             Devel::TypeTiny::Perl58Compat
23             Error::TypeTiny
24             Error::TypeTiny::Assertion
25             Error::TypeTiny::Compilation
26             Error::TypeTiny::WrongNumberOfParameters
27             Eval::TypeTiny
28             Eval::TypeTiny::CodeAccumulator
29             Eval::TypeTiny::Sandbox
30             Exporter::Tiny
31             Reply::Plugin::TypeTiny
32             Test::TypeTiny
33             Type::Coercion
34             Type::Coercion::FromMoose
35             Type::Coercion::Union
36             Type::Library
37             Type::Params
38             Type::Params::Alternatives
39             Type::Params::Parameter
40             Type::Params::Signature
41             Type::Parser
42             Type::Parser::AstBuilder
43             Type::Parser::Token
44             Type::Parser::TokenStream
45             Type::Registry
46             Types::Common
47             Types::Common::Numeric
48             Types::Common::String
49             Types::Standard
50             Types::Standard::_Stringable
51             Types::Standard::ArrayRef
52             Types::Standard::CycleTuple
53             Types::Standard::Dict
54             Types::Standard::HashRef
55             Types::Standard::Map
56             Types::Standard::ScalarRef
57             Types::Standard::StrMatch
58             Types::Standard::Tied
59             Types::Standard::Tuple
60             Types::TypeTiny
61             Type::Tie
62             Type::Tie::ARRAY
63             Type::Tie::BASE
64             Type::Tie::HASH
65             Type::Tie::SCALAR
66             Type::Tiny
67             Type::Tiny::_DeclaredType
68             Type::Tiny::_HalfOp
69             Type::Tiny::Bitfield
70             Type::Tiny::Class
71             Type::Tiny::ConstrainedObject
72             Type::Tiny::Duck
73             Type::Tiny::Enum
74             Type::Tiny::Intersection
75             Type::Tiny::Role
76             Type::Tiny::Union
77             Type::Utils
78             );
79              
80 310     310   2388 use Scalar::Util qw( blessed );
  310         684  
  310         33821  
81 310     310   124832 use Types::TypeTiny ();
  310         983  
  310         162937  
82              
83             our $SafePackage = sprintf 'package %s;', __PACKAGE__;
84              
85 15     15   91 sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }
  15         74  
86              
87 40155 50   40155   183269 sub _swap { $_[2] ? @_[ 1, 0 ] : @_[ 0, 1 ] }
88              
89             BEGIN {
90 310   33 310   3245 my $support_smartmatch = 0+ !!( $] >= 5.010001 && $] <= 5.041002 );
91 310         24063 eval qq{ sub SUPPORT_SMARTMATCH () { !! $support_smartmatch } };
92            
93 310         1661 my $fixed_precedence = 0+ !!( $] >= 5.014 );
94 310         18953 eval qq{ sub _FIXED_PRECEDENCE () { !! $fixed_precedence } };
95            
96             my $try_xs =
97             exists( $ENV{PERL_TYPE_TINY_XS} ) ? !!$ENV{PERL_TYPE_TINY_XS}
98             : exists( $ENV{PERL_ONLY} ) ? !$ENV{PERL_ONLY}
99 310 50       2805 : 1;
    100          
100            
101 310         684 my $use_xs = 0;
102 310 100       1637 $try_xs and eval {
103 308         2276 require Type::Tiny::XS;
104 308         4259 'Type::Tiny::XS'->VERSION( $Type::Tiny::XS_VERSION );
105 308         1400 $use_xs++;
106             };
107            
108             *_USE_XS =
109             $use_xs
110             ? sub () { !!1 }
111 310 100       1666 : sub () { !!0 };
112            
113             *_USE_MOUSE =
114             $try_xs
115 288 50   288   5290 ? sub () { $INC{'Mouse/Util.pm'} and Mouse::Util::MOUSE_XS() }
116 310 100       1837 : sub () { !!0 };
117            
118 310         692 my $strict_mode = 0;
119 310   100     3217 $ENV{$_} && ++$strict_mode for qw(
120             EXTENDED_TESTING
121             AUTHOR_TESTING
122             RELEASE_TESTING
123             PERL_STRICT
124             );
125 310 100       14335 *_STRICT_MODE = $strict_mode ? sub () { !!1 } : sub () { !!0 };
126             } #/ BEGIN
127              
128             {
129              
130             sub _install_overloads {
131 310     310   1926 no strict 'refs';
  310         675  
  310         15684  
132 310     310   1723 no warnings 'redefine', 'once';
  310         659  
  310         4439712  
133            
134             # Coverage is checked on Perl 5.26
135 1666 50   1666   10457 if ( $] < 5.010 ) { # uncoverable statement
136 0         0 require overload; # uncoverable statement
137 0         0 push @_, fallback => 1; # uncoverable statement
138 0         0 goto \&overload::OVERLOAD; # uncoverable statement
139             }
140            
141 1666         5242 my $class = shift;
142 1666     0   6866 *{ $class . '::((' } = sub { };
  1666         12823  
143 1666     0   5558 *{ $class . '::()' } = sub { };
  1666         7182  
144 1666         3336 *{ $class . '::()' } = do { my $x = 1; \$x };
  1666         4797  
  1666         3201  
  1666         3594  
145 1666         5802 while ( @_ ) {
146 7289         12003 my $f = shift;
147 7289 100       14509 *{ $class . '::(' . $f } = ref $_[0] ? shift : do {
  7289         43929  
148 695         2202 my $m = shift;
149 873     873   1990434 sub { shift->$m( @_ ) }
150 695         2881 };
151             }
152             } #/ sub _install_overloads
153             }
154              
155             __PACKAGE__->_install_overloads(
156             q("") => sub {
157 51375 50   51375   355595 caller =~ m{^(Moo::HandleMoose|Sub::Quote)}
158             ? $_[0]->_stringify_no_magic
159             : $_[0]->display_name;
160             },
161 49933     49933   154284 q(bool) => sub { 1 },
162             q(&{}) => "_overload_coderef",
163             q(|) => sub {
164 65     65   316611 my @tc = _swap @_;
165 65         134 if ( !_FIXED_PRECEDENCE && $_[2] ) {
166             if ( blessed $tc[0] ) {
167             if ( blessed $tc[0] eq "Type::Tiny::_HalfOp" ) {
168             my $type = $tc[0]->{type};
169             my $param = $tc[0]->{param};
170             my $op = $tc[0]->{op};
171             require Type::Tiny::Union;
172             return "Type::Tiny::_HalfOp"->new(
173             $op,
174             $param,
175             "Type::Tiny::Union"->new_by_overload( type_constraints => [ $type, $tc[1] ] ),
176             );
177             } #/ if ( blessed $tc[0] eq...)
178             } #/ if ( blessed $tc[0] )
179             elsif ( ref $tc[0] eq 'ARRAY' ) {
180             require Type::Tiny::_HalfOp;
181             return "Type::Tiny::_HalfOp"->new( '|', @tc );
182             }
183             } #/ if ( !_FIXED_PRECEDENCE...)
184 65         13091 require Type::Tiny::Union;
185 65         365 return "Type::Tiny::Union"->new_by_overload( type_constraints => \@tc );
186             },
187             q(&) => sub {
188 40060     40060   2669787 my @tc = _swap @_;
189 40060         77711 if ( !_FIXED_PRECEDENCE && $_[2] ) {
190             if ( blessed $tc[0] ) {
191             if ( blessed $tc[0] eq "Type::Tiny::_HalfOp" ) {
192             my $type = $tc[0]->{type};
193             my $param = $tc[0]->{param};
194             my $op = $tc[0]->{op};
195             require Type::Tiny::Intersection;
196             return "Type::Tiny::_HalfOp"->new(
197             $op,
198             $param,
199             "Type::Tiny::Intersection"->new_by_overload( type_constraints => [ $type, $tc[1] ] ),
200             );
201             } #/ if ( blessed $tc[0] eq...)
202             } #/ if ( blessed $tc[0] )
203             elsif ( ref $tc[0] eq 'ARRAY' ) {
204             require Type::Tiny::_HalfOp;
205             return "Type::Tiny::_HalfOp"->new( '&', @tc );
206             }
207             } #/ if ( !_FIXED_PRECEDENCE...)
208 40060         297011 require Type::Tiny::Intersection;
209 40060         178477 "Type::Tiny::Intersection"->new_by_overload( type_constraints => \@tc );
210             },
211 74     74   244596 q(~) => sub { shift->complementary_type },
212 715     715   8690 q(==) => sub { $_[0]->equals( $_[1] ) },
213 1     1   3 q(!=) => sub { not $_[0]->equals( $_[1] ) },
214 8     8   86 q(<) => sub { my $m = $_[0]->can( 'is_subtype_of' ); $m->( _swap @_ ) },
  8         22  
215             q(>) => sub {
216 10     10   117 my $m = $_[0]->can( 'is_subtype_of' );
217 10         31 $m->( reverse _swap @_ );
218             },
219 6     6   71 q(<=) => sub { my $m = $_[0]->can( 'is_a_type_of' ); $m->( _swap @_ ) },
  6         18  
220             q(>=) => sub {
221 6     6   100 my $m = $_[0]->can( 'is_a_type_of' );
222 6         19 $m->( reverse _swap @_ );
223             },
224 41     41   22036 q(eq) => sub { "$_[0]" eq "$_[1]" },
225 0 0   0   0 q(cmp) => sub { $_[2] ? ( "$_[1]" cmp "$_[0]" ) : ( "$_[0]" cmp "$_[1]" ) },
226 1     1   68 q(0+) => sub { $_[0]{uniq} },
227 4 100 50 4   728223 q(/) => sub { ( _STRICT_MODE xor $_[2] ) ? $_[0] : $_[1] },
228             );
229              
230             __PACKAGE__->_install_overloads(
231             q(~~) => sub { $_[0]->check( $_[1] ) },
232             ) if Type::Tiny::SUPPORT_SMARTMATCH;
233              
234             # Would be easy to just return sub { $self->assert_return(@_) }
235             # but try to build a more efficient coderef whenever possible.
236             #
237             sub _overload_coderef {
238 15226     15226   39862 my $self = shift;
239            
240             # Bypass generating a coderef if we've already got the best possible one.
241             #
242 15226 100       52822 return $self->{_overload_coderef} if $self->{_overload_coderef_no_rebuild};
243            
244             # Subclasses of Type::Tiny might override assert_return to do some kind
245             # of interesting thing. In that case, we can't rely on it having identical
246             # behaviour to Type::Tiny::inline_assert.
247             #
248             $self->{_overrides_assert_return} =
249             ( $self->can( 'assert_return' ) != \&assert_return )
250 15207 100       59924 unless exists $self->{_overrides_assert_return};
251            
252 15207 100       57182 if ( $self->{_overrides_assert_return} ) {
    100          
253 1   33     11 $self->{_overload_coderef} ||= do {
254 1         2 Scalar::Util::weaken( my $weak = $self );
255 1     2   3 sub { $weak->assert_return( @_ ) };
  2         5  
256             };
257 1         2 ++$self->{_overload_coderef_no_rebuild};
258             }
259             elsif ( exists( &Sub::Quote::quote_sub ) ) {
260            
261             # Use `=` instead of `||=` because we want to overwrite non-Sub::Quote
262             # coderef if possible.
263 162 100       533 $self->{_overload_coderef} = $self->can_be_inlined
264             ? Sub::Quote::quote_sub(
265             $self->inline_assert( '$_[0]' ),
266             )
267             : Sub::Quote::quote_sub(
268             $self->inline_assert( '$_[0]', '$type' ),
269             { '$type' => \$self },
270             );
271 162         16187 ++$self->{_overload_coderef_no_rebuild};
272             } #/ elsif ( exists( &Sub::Quote::quote_sub...))
273             else {
274 15044         96027 require Eval::TypeTiny;
275 15044 100 66     68851 $self->{_overload_coderef} ||= $self->can_be_inlined
276             ? Eval::TypeTiny::eval_closure(
277             source => sprintf(
278             'sub { %s }', $self->inline_assert( '$_[0]', undef, no_wrapper => 1 )
279             ),
280             description => sprintf( "compiled assertion 'assert_%s'", $self ),
281             )
282             : Eval::TypeTiny::eval_closure(
283             source => sprintf(
284             'sub { %s }', $self->inline_assert( '$_[0]', '$type', no_wrapper => 1 )
285             ),
286             description => sprintf( "compiled assertion 'assert_%s'", $self ),
287             environment => { '$type' => \$self },
288             );
289             } #/ else [ if ( $self->{_overrides_assert_return...})]
290            
291 15207         126042 $self->{_overload_coderef};
292             } #/ sub _overload_coderef
293              
294             our %ALL_TYPES;
295              
296             my $QFS;
297             my $uniq = 1;
298              
299             sub new {
300 95908     95908 1 2705324 my $class = shift;
301 95908 50       424794 my %params = ( @_ == 1 ) ? %{ $_[0] } : @_;
  0         0  
302            
303 95908         240942 for ( qw/ name display_name library / ) {
304 287724 100       743532 $params{$_} = $params{$_} . '' if defined $params{$_};
305             }
306            
307 95908         176758 my $level = 0;
308 95908   66     399038 while ( not exists $params{definition_context} and $level < 20 ) {
309 235192   66     487496 our $_TT_GUTS ||= do {
310 297         20554 my $g = join '|', map quotemeta, grep !m{^Types::}, @InternalPackages;
311 297         211456 qr/\A(?:$g)\z/o
312             };
313 235192         500112 my $package = caller $level;
314 235192 100       1458816 if ( $package !~ $_TT_GUTS ) {
315 95908         516486 @{ $params{definition_context} = {} }{ qw/ package file line / } = caller $level;
  95908         550003  
316             }
317 235192         829996 ++$level;
318             }
319            
320 95908 100       231061 if ( exists $params{parent} ) {
321             $params{parent} =
322             ref( $params{parent} ) =~ /^Type::Tiny\b/
323             ? $params{parent}
324 12782 50       62557 : Types::TypeTiny::to_TypeTiny( $params{parent} );
325            
326             _croak "Parent must be an instance of %s", __PACKAGE__
327             unless blessed( $params{parent} )
328 12782 50 33     54319 && $params{parent}->isa( __PACKAGE__ );
329            
330 12782 100 100     40718 if ( $params{parent}->deprecated and not exists $params{deprecated} ) {
331 3         8 $params{deprecated} = 1;
332             }
333             } #/ if ( exists $params{parent...})
334            
335 95908 100 66     423479 if ( exists $params{constraint}
      100        
336             and defined $params{constraint}
337             and not ref $params{constraint} )
338             {
339 84         649 require Eval::TypeTiny;
340 84         218 my $code = $params{constraint};
341 84         644 $params{constraint} = Eval::TypeTiny::eval_closure(
342             source => sprintf( 'sub ($) { %s }', $code ),
343             description => "anonymous check",
344             );
345             $params{inlined} ||= sub {
346 283     283   724 my ( $type ) = @_;
347 283 100       1147 my $inlined = $_ eq '$_' ? "do { $code }" : "do { local \$_ = $_; $code }";
348 283 100       588 $type->has_parent ? ( undef, $inlined ) : $inlined;
349             }
350 84 50 33     799 if ( !exists $params{parent} or $params{parent}->can_be_inlined );
      66        
351             } #/ if ( exists $params{constraint...})
352            
353             # canonicalize to a boolean
354 95908         245328 $params{deprecated} = !!$params{deprecated};
355            
356 95908 100       293298 $params{name} = "__ANON__" unless exists $params{name};
357 95908         232693 $params{uniq} = $uniq++;
358            
359 95908 100       266351 if ( $params{name} ne "__ANON__" ) {
360            
361             # First try a fast ASCII-only expression, but fall back to Unicode
362             $params{name} =~ /^_{0,2}[A-Z][A-Za-z0-9_]+$/sm
363             or eval q( use 5.008; $params{name} =~ /^_{0,2}\p{Lu}[\p{L}0-9_]+$/sm )
364 13289 100 66     87881 or _croak '"%s" is not a valid type name', $params{name};
  1         27  
  1         5  
365             }
366            
367 95907 100 100     233023 if ( exists $params{coercion} and !ref $params{coercion} and $params{coercion} )
      100        
368             {
369             $params{parent}->has_coercion
370 2 50       7 or _croak
371             "coercion => 1 requires type to have a direct parent with a coercion";
372            
373 2         9 $params{coercion} = $params{parent}->coercion->type_coercion_map;
374             }
375            
376 95907 100 100     725941 if ( !exists $params{inlined}
      100        
      100        
      100        
      100        
377             and exists $params{constraint}
378             and ( !exists $params{parent} or $params{parent}->can_be_inlined )
379             and $QFS ||= "Sub::Quote"->can( "quoted_from_sub" ) )
380             {
381 6 100       12 my ( undef, $perlstring, $captures ) = @{ $QFS->( $params{constraint} ) || [] };
  6         29  
382            
383             $params{inlined} = sub {
384 28     28   70 my ( $self, $var ) = @_;
385 28 50       175 my $code = Sub::Quote::inlinify(
386             $perlstring,
387             $var,
388             $var eq q($_) ? '' : "local \$_ = $var;",
389             1,
390             );
391 28 100       794 $code = sprintf( '%s and %s', $self->parent->inline_check( $var ), $code )
392             if $self->has_parent;
393 28         78 return $code;
394             }
395 6 100 100     532 if $perlstring && !$captures;
396             } #/ if ( !exists $params{inlined...})
397            
398 95907         246021 my $self = bless \%params, $class;
399            
400 95907 100       230800 unless ( $params{tmp} ) {
401 95849         244446 my $uniq = $self->{uniq};
402            
403 95849         295086 $ALL_TYPES{$uniq} = $self;
404 95849         205294 Scalar::Util::weaken( $ALL_TYPES{$uniq} );
405            
406 95849         168792 my $tmp = $self;
407 95849         194396 Scalar::Util::weaken( $tmp );
408 95849     0   479883 $Moo::HandleMoose::TYPE_MAP{ $self->_stringify_no_magic } = sub { $tmp };
  0         0  
409             } #/ unless ( $params{tmp} )
410            
411 95907 100       375510 if ( ref( $params{coercion} ) eq q(CODE) ) {
    100          
412 2         16 require Types::Standard;
413 2         7 my $code = delete( $params{coercion} );
414 2         11 $self->{coercion} = $self->_build_coercion;
415 2         10 $self->coercion->add_type_coercions( Types::Standard::Any(), $code );
416             }
417             elsif ( ref( $params{coercion} ) eq q(ARRAY) ) {
418 5         14 my $arr = delete( $params{coercion} );
419 5         24 $self->{coercion} = $self->_build_coercion;
420 5         16 $self->coercion->add_type_coercions( @$arr );
421             }
422            
423             # Documenting this here because it's too weird to be in the pod.
424             # There's a secret attribute called "_build_coercion" which takes a
425             # coderef. If present, then when $type->coercion is lazy built,
426             # the blank Type::Coercion object gets passed to the coderef,
427             # allowing the coderef to manipulate it a little. This is used by
428             # Types::TypeTiny to allow it to build a coercion for the TypeTiny
429             # type constraint without needing to load Type::Coercion yet.
430            
431 95907 100       226180 if ( $params{my_methods} ) {
432 1125         8172 require Eval::TypeTiny;
433             Scalar::Util::reftype( $params{my_methods}{$_} ) eq 'CODE'
434             and /\A[^0-9\W]\w+\z/
435             and Eval::TypeTiny::set_subname(
436             sprintf( "%s::my_%s", $self->qualified_name, $_ ),
437             $params{my_methods}{$_},
438 1125   66     2181 ) for keys %{ $params{my_methods} };
  1125   66     14364  
439             } #/ if ( $params{my_methods...})
440            
441             # In general, mutating a type constraint after it's been created
442             # is a bad idea and will probably not work. However some places are
443             # especially harmful and can lead to confusing errors, so allow
444             # subclasses to lock down particular keys.
445             #
446             $self->_lockdown( sub {
447 40538     40538   193366 &Internals::SvREADONLY( $_, !!1 ) for @_;
448 95907         481092 } );
449            
450 95907         896381 return $self;
451             } #/ sub new
452              
453       55369     sub _lockdown {}
454              
455             sub DESTROY {
456 81792     81792   414876 my $self = shift;
457 81792         293506 delete( $ALL_TYPES{ $self->{uniq} } );
458 81792         188099 delete( $Moo::HandleMoose::TYPE_MAP{ $self->_stringify_no_magic } );
459 81792         1162047 return;
460             }
461              
462             sub _clone {
463 97     97   201 my $self = shift;
464 97         198 my %opts;
465 97         1207 $opts{$_} = $self->{$_} for qw< name display_name message >;
466 97         511 $self->create_child_type( %opts );
467             }
468              
469             sub _stringify_no_magic {
470 177642     177642   1205842 sprintf(
471             '%s=%s(0x%08x)', blessed( $_[0] ), Scalar::Util::reftype( $_[0] ),
472             Scalar::Util::refaddr( $_[0] )
473             );
474             }
475              
476             our $DD;
477              
478             sub _dd {
479 2598 50   2598   9606 @_ = $_ unless @_;
480 2598         6168 my ( $value ) = @_;
481            
482 2598 100       9267 goto $DD if ref( $DD ) eq q(CODE);
483            
484 2596         13801 require B;
485            
486             !defined $value ? 'Undef'
487             : !ref $value ? sprintf( 'Value %s', B::perlstring( $value ) )
488 2596 100       27144 : do {
    100          
489 1533 50       4725 my $N = 0+ ( defined( $DD ) ? $DD : 72 );
490 1533         79864 require Data::Dumper;
491 1533         902974 local $Data::Dumper::Indent = 0;
492 1533         3092 local $Data::Dumper::Useqq = 1;
493 1533         2982 local $Data::Dumper::Terse = 1;
494 1533         2998 local $Data::Dumper::Sortkeys = 1;
495 1533         3083 local $Data::Dumper::Maxdepth = 2;
496 1533         2935 my $str;
497             eval {
498 1533     0   14642 local $SIG{__WARN__} = sub {};
499 1533         8488 $str = Data::Dumper::Dumper( $value );
500 1533 100       136868 $str = substr( $str, 0, $N - 12 ) . '...' . substr( $str, -1, 1 )
501             if length( $str ) >= $N;
502 1533         14823 1;
503 1533 50       4252 } or do { $str = 'which cannot be dumped' };
  0         0  
504 1533         23791 "Reference $str";
505             } #/ do
506             } #/ sub _dd
507              
508             sub _loose_to_TypeTiny {
509 32431     32431   61884 my $caller = caller( 1 ); # assumption
510             map +(
511             ref( $_ )
512             ? Types::TypeTiny::to_TypeTiny( $_ )
513 32431 100       109551 : do { require Type::Utils; Type::Utils::dwim_type( $_, for => $caller ) }
  2         831  
  2         12  
514             ), @_;
515             }
516              
517 110697     110697 1 3528387 sub name { $_[0]{name} }
518 53043   66 53043 1 592663 sub display_name { $_[0]{display_name} ||= $_[0]->_build_display_name }
519 161091     161091 1 412057 sub parent { $_[0]{parent} }
520 441898   66 441898 1 1914898 sub constraint { $_[0]{constraint} ||= $_[0]->_build_constraint }
521              
522             sub compiled_check {
523 134689   66 134689 1 743938 $_[0]{compiled_type_constraint} ||= $_[0]->_build_compiled_check;
524             }
525 20651   66 20651 1 335374 sub coercion { $_[0]{coercion} ||= $_[0]->_build_coercion }
526 28     28 1 99 sub message { $_[0]{message} }
527 68     68 1 368945 sub library { $_[0]{library} }
528 51715     51715 1 208051 sub inlined { $_[0]{inlined} }
529 34267     34267 1 157801 sub deprecated { $_[0]{deprecated} }
530 1363     1363 1 12618 sub constraint_generator { $_[0]{constraint_generator} }
531 1144     1144 1 4943 sub inline_generator { $_[0]{inline_generator} }
532 1065   66 1065 1 6828 sub name_generator { $_[0]{name_generator} ||= $_[0]->_build_name_generator }
533 218     218 1 1689 sub coercion_generator { $_[0]{coercion_generator} }
534 970     970 1 8075 sub parameters { $_[0]{parameters} }
535 0   0 0 1 0 sub moose_type { $_[0]{moose_type} ||= $_[0]->_build_moose_type }
536 0   0 0 1 0 sub mouse_type { $_[0]{mouse_type} ||= $_[0]->_build_mouse_type }
537 102     102 1 1961 sub deep_explanation { $_[0]{deep_explanation} }
538 1970   66 1970 1 15602 sub my_methods { $_[0]{my_methods} ||= $_[0]->_build_my_methods }
539 25     25 1 47 sub sorter { $_[0]{sorter} }
540 24703   66 24703 1 128782 sub exception_class { $_[0]{exception_class} ||= $_[0]->_build_exception_class }
541              
542 598136     598136 1 1788323 sub has_parent { exists $_[0]{parent} }
543 0     0 1 0 sub has_library { exists $_[0]{library} }
544 146175     146175 1 612596 sub has_inlined { exists $_[0]{inlined} }
545 16301     16301 1 75135 sub has_constraint_generator { exists $_[0]{constraint_generator} }
546 879     879 1 6813 sub has_inline_generator { exists $_[0]{inline_generator} }
547 2199     2199 1 13025 sub has_coercion_generator { exists $_[0]{coercion_generator} }
548 501     501 1 2321 sub has_parameters { exists $_[0]{parameters} }
549 921     921 1 4305 sub has_message { defined $_[0]{message} }
550 102     102 1 496 sub has_deep_explanation { exists $_[0]{deep_explanation} }
551 74     74 1 151 sub has_sorter { exists $_[0]{sorter} }
552              
553             sub _default_message {
554 893   66 893   3970 $_[0]{_default_message} ||= $_[0]->_build_default_message;
555             }
556              
557             sub has_coercion {
558 32000 100   32000 1 91000 $_[0]->coercion if $_[0]{_build_coercion}; # trigger auto build thing
559 32000 100       165352 $_[0]{coercion} and !!@{ $_[0]{coercion}->type_coercion_map };
  19894         50332  
560             }
561              
562             sub _assert_coercion {
563 647     647   1034 my $self = shift;
564 647 100       2552 return $self->coercion if $self->{_build_coercion}; # trigger auto build thing
565             _croak "No coercion for this type constraint"
566             unless $self->has_coercion
567 511 100 66     1219 && @{ $self->coercion->type_coercion_map };
  502         1346  
568 502         1196 $self->coercion;
569             }
570              
571             my $null_constraint = sub { !!1 };
572              
573             sub _build_display_name {
574 13085     13085   31643 shift->name;
575             }
576              
577             sub _build_constraint {
578 4646     4646   33223 return $null_constraint;
579             }
580              
581             sub _is_null_constraint {
582 381585     381585   739543 shift->constraint == $null_constraint;
583             }
584              
585             sub _build_coercion {
586 12953     12953   238810 require Type::Coercion;
587 12953         22696 my $self = shift;
588 12953         30501 my %opts = ( type_constraint => $self );
589 12953 100       36615 $opts{display_name} = "to_$self" unless $self->is_anon;
590 12953         76141 my $coercion = "Type::Coercion"->new( %opts );
591 12953 100       36437 $self->{_build_coercion}->( $coercion ) if ref $self->{_build_coercion};
592 12953         46472 $coercion;
593             }
594              
595             sub _build_default_message {
596 192     192   359 my $self = shift;
597 192         635 $self->{is_using_default_message} = 1;
598 67     67   296 return sub { sprintf '%s did not pass type constraint', _dd( $_[0] ) }
599 192 100       677 if "$self" eq "__ANON__";
600 166         422 my $name = "$self";
601             return sub {
602 823     823   2709 sprintf '%s did not pass type constraint "%s"', _dd( $_[0] ), $name;
603 166         1381 };
604             } #/ sub _build_default_message
605              
606             sub _build_name_generator {
607 249     249   578 my $self = shift;
608             return sub {
609 902   33 902   7787 defined && s/[\x00-\x1F]//smg for ( my ( $s, @a ) = @_ );
610 902 100 100     10836 sprintf( '%s[%s]', $s, join q[,], map !defined() ? 'undef' : !ref() && /\W/ ? B::perlstring($_) : $_, @a );
    50          
611 249         2483 };
612             }
613              
614             sub _build_compiled_check {
615 48230     48230   89650 my $self = shift;
616            
617 48230         87988 local our $AvoidCallbacks = 0;
618            
619 48230 100 100     107131 if ( $self->_is_null_constraint and $self->has_parent ) {
620 3519         9540 return $self->parent->compiled_check;
621             }
622            
623 44711         288275 require Eval::TypeTiny;
624 44711 100       139376 return Eval::TypeTiny::eval_closure(
625             source => sprintf( 'sub ($) { %s }', $self->inline_check( '$_[0]' ) ),
626             description => sprintf( "compiled check '%s'", $self ),
627             ) if $self->can_be_inlined;
628            
629 40262         87303 my @constraints;
630 40262 100       72638 push @constraints, $self->parent->compiled_check if $self->has_parent;
631 40262 50       80517 push @constraints, $self->constraint if !$self->_is_null_constraint;
632 40262 50       105634 return $null_constraint unless @constraints;
633            
634             return sub ($) {
635 3498     3498   507919 local $_ = $_[0];
        575      
        575      
        558      
        572      
636 3498         5925 for my $c ( @constraints ) {
637 5936 100       18070 return unless $c->( @_ );
638             }
639 2322         17880 return !!1;
640 40262         325420 };
641             } #/ sub _build_compiled_check
642              
643             sub _build_exception_class {
644 12748     12748   19253 my $self = shift;
645 12748 100       24531 return $self->parent->exception_class if $self->has_parent;
646 1169         143408 require Error::TypeTiny::Assertion;
647 1169         7131 return 'Error::TypeTiny::Assertion';
648             }
649              
650             sub definition_context {
651 1     1 1 2 my $self = shift;
652             my $found = $self->find_parent(sub {
653 1 50   1   9 ref $_->{definition_context} and exists $_->{definition_context}{file};
654 1         8 });
655 1 50       6 $found ? $found->{definition_context} : {};
656             }
657              
658             sub find_constraining_type {
659 4157     4157 1 5329 my $self = shift;
660 4157 100 100     6966 if ( $self->_is_null_constraint and $self->has_parent ) {
661 818         1765 return $self->parent->find_constraining_type;
662             }
663 3339         6260 $self;
664             }
665              
666             sub type_default {
667 752     752 1 366264 my ( $self, @args ) = @_;
668 752 100       2994 if ( exists $self->{type_default} ) {
669 567 100       1736 if ( @args ) {
670 1         2 my $td = $self->{type_default};
671 1     1   5 return sub { local $_ = \@args; &$td; };
  1         2680  
  1         3  
672             }
673 566         3255 return $self->{type_default};
674             }
675 185 100       663 if ( my $parent = $self->parent ) {
676 183 100       657 return $parent->type_default( @args ) if $self->_is_null_constraint;
677             }
678 81         676 return undef;
679             }
680              
681             our @CMP;
682              
683             sub CMP_SUPERTYPE () { -1 }
684             sub CMP_EQUAL () { 0 }
685             sub CMP_EQUIVALENT () { '0E0' }
686             sub CMP_SUBTYPE () { 1 }
687             sub CMP_UNKNOWN () { ''; }
688              
689             # avoid getting mixed up with cmp operator at compile time
690             *cmp = sub {
691 1544     1544   48286 my ( $A, $B ) = _loose_to_TypeTiny( $_[0], $_[1] );
692 1544 50 33     6866 return unless blessed( $A ) && $A->isa( "Type::Tiny" );
693 1544 50 33     4541 return unless blessed( $B ) && $B->isa( "Type::Tiny" );
694 1544         4282 for my $comparator ( @CMP ) {
695 2045         5021 my $result = $comparator->( $A, $B );
696 2045 100       5410 next if $result eq CMP_UNKNOWN;
697 1185 100       2687 if ( $result eq CMP_EQUIVALENT ) {
698 51 100       159 my $prefer = @_ == 3 ? $_[2] : CMP_EQUAL;
699 51         194 return $prefer;
700             }
701 1134         3651 return $result;
702             }
703 359         756 return CMP_UNKNOWN;
704             };
705              
706             push @CMP, sub {
707             my ( $A, $B ) = @_;
708             return CMP_EQUAL
709             if Scalar::Util::refaddr( $A ) == Scalar::Util::refaddr( $B );
710            
711             return CMP_EQUIVALENT
712             if Scalar::Util::refaddr( $A->compiled_check ) ==
713             Scalar::Util::refaddr( $B->compiled_check );
714            
715             my $A_stem = $A->find_constraining_type;
716             my $B_stem = $B->find_constraining_type;
717             return CMP_EQUIVALENT
718             if Scalar::Util::refaddr( $A_stem ) == Scalar::Util::refaddr( $B_stem );
719             return CMP_EQUIVALENT
720             if Scalar::Util::refaddr( $A_stem->compiled_check ) ==
721             Scalar::Util::refaddr( $B_stem->compiled_check );
722            
723             if ( $A_stem->can_be_inlined and $B_stem->can_be_inlined ) {
724             return CMP_EQUIVALENT
725             if $A_stem->inline_check( '$WOLFIE' ) eq $B_stem->inline_check( '$WOLFIE' );
726             }
727            
728             A_IS_SUBTYPE: {
729             my $A_prime = $A_stem;
730             while ( $A_prime->has_parent ) {
731             $A_prime = $A_prime->parent;
732             return CMP_SUBTYPE
733             if Scalar::Util::refaddr( $A_prime ) == Scalar::Util::refaddr( $B_stem );
734             return CMP_SUBTYPE
735             if Scalar::Util::refaddr( $A_prime->compiled_check ) ==
736             Scalar::Util::refaddr( $B_stem->compiled_check );
737             if ( $A_prime->can_be_inlined and $B_stem->can_be_inlined ) {
738             return CMP_SUBTYPE
739             if $A_prime->inline_check( '$WOLFIE' ) eq $B_stem->inline_check( '$WOLFIE' );
740             }
741             } #/ while ( $A_prime->has_parent)
742             } #/ A_IS_SUBTYPE:
743            
744             B_IS_SUBTYPE: {
745             my $B_prime = $B_stem;
746             while ( $B_prime->has_parent ) {
747             $B_prime = $B_prime->parent;
748             return CMP_SUPERTYPE
749             if Scalar::Util::refaddr( $B_prime ) == Scalar::Util::refaddr( $A_stem );
750             return CMP_SUPERTYPE
751             if Scalar::Util::refaddr( $B_prime->compiled_check ) ==
752             Scalar::Util::refaddr( $A_stem->compiled_check );
753             if ( $A_stem->can_be_inlined and $B_prime->can_be_inlined ) {
754             return CMP_SUPERTYPE
755             if $B_prime->inline_check( '$WOLFIE' ) eq $A_stem->inline_check( '$WOLFIE' );
756             }
757             } #/ while ( $B_prime->has_parent)
758             } #/ B_IS_SUBTYPE:
759            
760             return CMP_UNKNOWN;
761             };
762              
763             sub equals {
764 777     777 1 2557 my $result = Type::Tiny::cmp( $_[0], $_[1] );
765 777 50       1759 return unless defined $result;
766 777         6404 $result eq CMP_EQUAL;
767             }
768              
769             sub is_subtype_of {
770 101     101 1 381 my $result = Type::Tiny::cmp( $_[0], $_[1], CMP_SUBTYPE );
771 101 50       256 return unless defined $result;
772 101         519 $result eq CMP_SUBTYPE;
773             }
774              
775             sub is_supertype_of {
776 21     21 1 349 my $result = Type::Tiny::cmp( $_[0], $_[1], CMP_SUBTYPE );
777 21 50       54 return unless defined $result;
778 21         102 $result eq CMP_SUPERTYPE;
779             }
780              
781             sub is_a_type_of {
782 601     601 1 7502 my $result = Type::Tiny::cmp( $_[0], $_[1] );
783 601 50       1659 return unless defined $result;
784 601 100 100     6114 $result eq CMP_SUBTYPE or $result eq CMP_EQUAL or $result eq CMP_EQUIVALENT;
785             }
786              
787             sub strictly_equals {
788 14433     14433 1 27965 my ( $self, $other ) = _loose_to_TypeTiny( @_ );
789 14433 50 33     41316 return unless blessed( $self ) && $self->isa( "Type::Tiny" );
790 14433 50 33     42635 return unless blessed( $other ) && $other->isa( "Type::Tiny" );
791 14433         69429 $self->{uniq} == $other->{uniq};
792             }
793              
794             sub is_strictly_subtype_of {
795 13865     13865 1 28960 my ( $self, $other ) = _loose_to_TypeTiny( @_ );
796 13865 50 33     43262 return unless blessed( $self ) && $self->isa( "Type::Tiny" );
797 13865 50 33     40057 return unless blessed( $other ) && $other->isa( "Type::Tiny" );
798            
799 13865 100       34962 return unless $self->has_parent;
800 11827 100       23986 $self->parent->strictly_equals( $other )
801             or $self->parent->is_strictly_subtype_of( $other );
802             }
803              
804             sub is_strictly_supertype_of {
805 2     2 1 11 my ( $self, $other ) = _loose_to_TypeTiny( @_ );
806 2 50 33     9 return unless blessed( $self ) && $self->isa( "Type::Tiny" );
807 2 50 33     6 return unless blessed( $other ) && $other->isa( "Type::Tiny" );
808            
809 2         4 $other->is_strictly_subtype_of( $self );
810             }
811              
812             sub is_strictly_a_type_of {
813 2587     2587 1 17986 my ( $self, $other ) = _loose_to_TypeTiny( @_ );
814 2587 50 33     13220 return unless blessed( $self ) && $self->isa( "Type::Tiny" );
815 2587 50 33     8188 return unless blessed( $other ) && $other->isa( "Type::Tiny" );
816            
817 2587 50       7525 $self->strictly_equals( $other ) or $self->is_strictly_subtype_of( $other );
818             }
819              
820             sub qualified_name {
821 15079     15079 1 26057 my $self = shift;
822             ( exists $self->{library} and $self->name ne "__ANON__" )
823             ? "$self->{library}::$self->{name}"
824 15079 100 66     49877 : $self->{name};
825             }
826              
827             sub is_anon {
828 42821     42821 1 66842 my $self = shift;
829 42821         107067 $self->name eq "__ANON__";
830             }
831              
832             sub parents {
833 38344     38344 1 60945 my $self = shift;
834 38344 100       72715 return unless $self->has_parent;
835 31908         63512 return ( $self->parent, $self->parent->parents );
836             }
837              
838             sub find_parent {
839 483     483 1 1059 my $self = shift;
840 483         1054 my ( $test ) = @_;
841            
842 483         2062 local ( $_, $. );
843 483         849 my $type = $self;
844 483         823 my $count = 0;
845 483         1661 while ( $type ) {
846 591 100       2122 if ( $test->( $_ = $type, $. = $count ) ) {
847 480 100       3047 return wantarray ? ( $type, $count ) : $type;
848             }
849             else {
850 111         272 $type = $type->parent;
851 111         276 $count++;
852             }
853             }
854            
855 3         11 return;
856             } #/ sub find_parent
857              
858             sub check {
859 143137     143137 1 511990 my $self = shift;
860 143137   66     933918 ( $self->{compiled_type_constraint} ||= $self->_build_compiled_check )->( @_ );
861             }
862              
863             sub _strict_check {
864 5633     5633   14339 my $self = shift;
865 5633         18113 local $_ = $_[0];
866            
867             my @constraints =
868             reverse
869 20206         36131 map { $_->constraint }
870 5633         26630 grep { not $_->_is_null_constraint } ( $self, $self->parents );
  33236         64040  
871            
872 5633         17367 for my $c ( @constraints ) {
873 15477 100       68764 return unless $c->( @_ );
874             }
875            
876 1567         13174 return !!1;
877             } #/ sub _strict_check
878              
879             sub get_message {
880 921     921 1 1562 my $self = shift;
881 921         1608 local $_ = $_[0];
882 921 100       2583 $self->has_message
883             ? $self->message->( @_ )
884             : $self->_default_message->( @_ );
885             }
886              
887             sub validate {
888 2     2 1 4 my $self = shift;
889            
890             return undef
891 2 50 33     11 if ( $self->{compiled_type_constraint} ||= $self->_build_compiled_check )
892             ->( @_ );
893            
894 2         20 local $_ = $_[0];
895 2         6 return $self->get_message( @_ );
896             } #/ sub validate
897              
898             sub validate_explain {
899 2158     2158 1 6257 my $self = shift;
900 2158         4004 my ( $value, $varname ) = @_;
901 2158 100       4129 $varname = '$_' unless defined $varname;
902            
903 2158 100       4182 return undef if $self->check( $value );
904            
905 1706 100       5778 if ( $self->has_parent ) {
906 1698         3560 my $parent = $self->parent->validate_explain( $value, $varname );
907             return [
908 1698 100       4841 sprintf( '"%s" is a subtype of "%s"', $self, $self->parent ),
909             @$parent
910             ]
911             if $parent;
912             }
913            
914 460 100       1359 my $message = sprintf(
915             '%s%s',
916             $self->get_message( $value ),
917             $varname eq q{$_} ? '' : sprintf( ' (in %s)', $varname ),
918             );
919            
920 460 100 66     1487 if ( $self->is_parameterized and $self->parent->has_deep_explanation ) {
921 102         272 my $deep = $self->parent->deep_explanation->( $self, $value, $varname );
922 102 50       897 return [ $message, @$deep ] if $deep;
923             }
924              
925 358     0   2325 local $SIG{__WARN__} = sub {};
926             return [
927 358         1344 $message,
928             sprintf( '"%s" is defined as: %s', $self, $self->_perlcode )
929             ];
930             } #/ sub validate_explain
931              
932             my $b;
933              
934             sub _perlcode {
935 358     358   662 my $self = shift;
936            
937 358         734 local our $AvoidCallbacks = 1;
938 358 100       1059 return $self->inline_check( '$_' )
939             if $self->can_be_inlined;
940            
941 12   66     48 $b ||= do {
942 7         646 local $@;
943 7         75 require B::Deparse;
944 7         431 my $tmp = "B::Deparse"->new;
945 7 50       687 $tmp->ambient_pragmas( strict => "all", warnings => "all" )
946             if $tmp->can( 'ambient_pragmas' );
947 7         40 $tmp;
948             };
949            
950 12         36 my $code = $b->coderef2text( $self->constraint );
951 12         134 $code =~ s/\s+/ /g;
952 12         87 return "sub $code";
953             } #/ sub _perlcode
954              
955             sub assert_valid {
956 87     87 1 13179 my $self = shift;
957            
958             return !!1
959 87 100 66     529 if ( $self->{compiled_type_constraint} ||= $self->_build_compiled_check )
960             ->( @_ );
961            
962 15         134 local $_ = $_[0];
963 15         93 $self->_failed_check( "$self", $_ );
964             } #/ sub assert_valid
965              
966             sub assert_return {
967 115083     115083 1 193899 my $self = shift;
968            
969             return $_[0]
970 115083 100 66     467622 if ( $self->{compiled_type_constraint} ||= $self->_build_compiled_check )
971             ->( @_ );
972            
973 1         5 local $_ = $_[0];
974 1         3 $self->_failed_check( "$self", $_ );
975             } #/ sub assert_return
976              
977             sub can_be_inlined {
978 190216     190216 1 547548 my $self = shift;
979 190216 100 100     368779 return $self->parent->can_be_inlined
980             if $self->has_parent && $self->_is_null_constraint;
981 162115 100 100     321193 return !!1
982             if !$self->has_parent && $self->_is_null_constraint;
983 148550         301589 return $self->has_inlined;
984             }
985              
986             sub inline_check {
987 69887     69887 1 148088 my $self = shift;
988 69887 50       137455 _croak 'Cannot inline type constraint check for "%s"', $self
989             unless $self->can_be_inlined;
990            
991 69887 100 100     133393 return $self->parent->inline_check( @_ )
992             if $self->has_parent && $self->_is_null_constraint;
993 57415 100 100     113535 return '(!!1)'
994             if !$self->has_parent && $self->_is_null_constraint;
995            
996 52975         105127 local $_ = $_[0];
997 52975         128378 my @r = $self->inlined->( $self, @_ );
998 52975 100 66     212686 if ( @r and not defined $r[0] ) {
999 7959 50       17813 _croak 'Inlining type constraint check for "%s" returned undef!', $self
1000             unless $self->has_parent;
1001 7959         19529 $r[0] = $self->parent->inline_check( @_ );
1002             }
1003             my $r = join " && " => map {
1004 52975 100 100     116796 /\A(?:[A-Z](?:\w)*::[A-Z](?:\w|::)*)\(\$\w+(?:\[\d+\]|\{[^}]+\})?\)\z/i ? $_ :
  64605 100       999629  
1005             /[;{}]/ && !/\Ado \{.+\}\z/ ? "do { $SafePackage $_ }" :
1006             "($_)"
1007             } @r;
1008 52975 100       1335142 return @r == 1 ? $r : "($r)";
1009             } #/ sub inline_check
1010              
1011             sub inline_assert {
1012 12748     12748 1 338081 require B;
1013 12748         20293 my $self = shift;
1014 12748         44148 my ( $varname, $typevarname, %extras ) = @_;
1015            
1016 12748   33     57567 $extras{exception_class} ||= $self->exception_class;
1017            
1018 12748         21702 my $inline_check;
1019 12748 100       28380 if ( $self->can_be_inlined ) {
    100          
1020 12650         37493 $inline_check = sprintf( '(%s)', $self->inline_check( $varname ) );
1021             }
1022             elsif ( $typevarname ) {
1023 97         210 $inline_check = sprintf( '%s->check(%s)', $typevarname, $varname );
1024             }
1025             else {
1026 1         7 _croak 'Cannot inline type constraint check for "%s"', $self;
1027             }
1028            
1029 12747         39995 my $do_wrapper = !delete $extras{no_wrapper};
1030            
1031 12747         20925 my $inline_throw;
1032 12747 100       26205 if ( $typevarname ) {
1033             $inline_throw = sprintf(
1034             'Type::Tiny::_failed_check(%s, %s, %s, %s)',
1035             $typevarname,
1036             B::perlstring( "$self" ),
1037             $varname,
1038             join(
1039 98         360 ',', map +( B::perlstring( $_ ) => B::perlstring( $extras{$_} ) ),
1040             sort keys %extras
1041             ),
1042             );
1043             } #/ if ( $typevarname )
1044             else {
1045             $inline_throw = sprintf(
1046             'Type::Tiny::_failed_check(%s, %s, %s, %s)',
1047             $self->{uniq},
1048             B::perlstring( "$self" ),
1049             $varname,
1050             join(
1051 12649         56907 ',', map +( B::perlstring( $_ ) => B::perlstring( $extras{$_} ) ),
1052             sort keys %extras
1053             ),
1054             );
1055             } #/ else [ if ( $typevarname ) ]
1056            
1057 12747 100       106518 $do_wrapper
1058             ? qq[do { no warnings "void"; $SafePackage $inline_check or $inline_throw; $varname };]
1059             : qq[ no warnings "void"; $SafePackage $inline_check or $inline_throw; $varname ];
1060             } #/ sub inline_assert
1061              
1062             sub _failed_check {
1063 438     438   25535 my ( $self, $name, $value, %attrs ) = @_;
1064 438 100 100     3571 $self = $ALL_TYPES{$self} if defined $self && !ref $self;
1065            
1066             my $exception_class = delete( $attrs{exception_class} )
1067 438   66     2911 || ( ref $self ? $self->exception_class : 'Error::TypeTiny::Assertion' );
1068 438         974 my $callback = delete( $attrs{on_die} );
1069              
1070 438 100       1855 if ( $self ) {
1071 437         2032 return $exception_class->throw_cb(
1072             $callback,
1073             message => $self->get_message( $value ),
1074             type => $self,
1075             value => $value,
1076             %attrs,
1077             );
1078             }
1079             else {
1080 1         4 return $exception_class->throw_cb(
1081             $callback,
1082             message => sprintf( '%s did not pass type constraint "%s"', _dd( $value ), $name ),
1083             value => $value,
1084             %attrs,
1085             );
1086             }
1087             } #/ sub _failed_check
1088              
1089             sub coerce {
1090 571     571 1 88590 my $self = shift;
1091 571         1711 $self->_assert_coercion->coerce( @_ );
1092             }
1093              
1094             sub check_coerce {
1095 4     4 1 12 my $self = shift;
1096 4 50       10 if ( $self->has_coercion ) {
1097 4         7 $self->_assert_coercion->check_coerce( @_ ) ;
1098             }
1099             else {
1100 0 0       0 $self->check( @_ ) ? $_[0] : undef;
1101             }
1102             }
1103              
1104             sub assert_coerce {
1105 64     64 1 554 my $self = shift;
1106 64         193 $self->_assert_coercion->assert_coerce( @_ );
1107             }
1108              
1109             sub is_parameterizable {
1110 16301     16301 1 46939 shift->has_constraint_generator;
1111             }
1112              
1113             sub is_parameterized {
1114 499     499 1 1748 shift->has_parameters;
1115             }
1116              
1117             {
1118             my %seen;
1119            
1120             sub ____make_key {
1121             #<<<
1122             join ',', map {
1123 1811     1811   5387 Types::TypeTiny::is_TypeTiny( $_ ) ? sprintf( '$Type::Tiny::ALL_TYPES{%s}', defined( $_->{uniq} ) ? $_->{uniq} : '____CANNOT_KEY____' ) :
1124 7 50       91 ref() eq 'ARRAY' ? do { $seen{$_}++ ? '____CANNOT_KEY____' : sprintf( '[%s]', ____make_key( @$_ ) ) } :
1125 18 50       207 ref() eq 'HASH' ? do { $seen{$_}++ ? '____CANNOT_KEY____' : sprintf( '{%s}', ____make_key( do { my %h = %$_; map +( $_, $h{$_} ), sort keys %h; } ) ) } :
  18         59  
  18         99  
1126 3 50       50 ref() eq 'SCALAR' || ref() eq 'REF' ? do { $seen{$_}++ ? '____CANNOT_KEY____' : sprintf( '\\(%s)', ____make_key( $$_ ) ) } :
1127             !defined() ? 'undef' :
1128 7898 50 66     213444 !ref() ? do { require B; B::perlstring( $_ ) } :
  4762 100       63692  
  4762 100       23380  
    100          
    100          
    100          
    100          
    100          
    100          
    100          
1129             '____CANNOT_KEY____';
1130             } @_;
1131             #>>>
1132             } #/ sub ____make_key
1133             my %param_cache;
1134            
1135             sub parameterize {
1136 1781     1781 1 12746864 my $self = shift;
1137            
1138 1781 0       7248 $self->is_parameterizable
    50          
1139             or @_
1140             ? _croak( "Type '%s' does not accept parameters", "$self" )
1141             : return ( $self );
1142            
1143 1781         10988 @_ = map Types::TypeTiny::to_TypeTiny( $_ ), @_;
1144            
1145             # Generate a key for caching parameterized type constraints,
1146             # but only if all the parameters are strings or type constraints.
1147 1781         5001 %seen = ();
1148 1781         9028 my $key = $self->____make_key( @_ );
1149 1781 100       8902 undef( $key ) if $key =~ /____CANNOT_KEY____/;
1150 1781 100 100     12814 return $param_cache{$key} if defined $key && defined $param_cache{$key};
1151            
1152 1363         3009 local $Type::Tiny::parameterize_type = $self;
1153 1363         3391 local $_ = $_[0];
1154 1363         2376 my $P;
1155            
1156 1363         6477 my ( $constraint, $compiled ) = $self->constraint_generator->( @_ );
1157            
1158 1320 100       44981 if ( Types::TypeTiny::is_TypeTiny( $constraint ) ) {
1159 441         1166 $P = $constraint;
1160             }
1161             else {
1162 879         9120 my %options = (
1163             constraint => $constraint,
1164             display_name => $self->name_generator->( $self, @_ ),
1165             parameters => [@_],
1166             );
1167 879 100       3920 $options{compiled_type_constraint} = $compiled
1168             if $compiled;
1169 879 100       4987 $options{inlined} = $self->inline_generator->( @_ )
1170             if $self->has_inline_generator;
1171             $options{type_default} = $self->{type_default_generator}->( @_ )
1172 879 100       6927 if exists $self->{type_default_generator}; # undocumented
1173             exists $options{$_} && !defined $options{$_} && delete $options{$_}
1174 879   66     18721 for keys %options;
      66        
1175            
1176 879         4672 $P = $self->create_child_type( %options );
1177            
1178 879 100       7417 if ( $self->has_coercion_generator ) {
1179 465         1834 my @args = @_;
1180             $P->{_build_coercion} = sub {
1181 218     218   601 my $coercion = shift;
1182 218         960 my $built = $self->coercion_generator->( $self, $P, @args );
1183 218 100       796 $coercion->add_type_coercions( @{ $built->type_coercion_map } ) if $built;
  111         310  
1184 218         990 $coercion->freeze;
1185 465         3887 };
1186             }
1187             } #/ else [ if ( Types::TypeTiny::is_TypeTiny...)]
1188            
1189 1320 100       5981 if ( defined $key ) {
1190 1284         4566 $param_cache{$key} = $P;
1191 1284         3106 Scalar::Util::weaken( $param_cache{$key} );
1192             }
1193            
1194 1320 100       4117 $P->coercion->freeze unless $self->has_coercion_generator;
1195            
1196 1320         9140 return $P;
1197             } #/ sub parameterize
1198             }
1199              
1200             sub check_parameter_count_for_parameterized_type {
1201 931     931 0 4611 my ( $library, $type_name, $args, $max_args, $min_args ) = @_;
1202 931 50       3302 $args = @$args if ref $args;
1203            
1204 931 100 66     16544 if ( ( defined $max_args and $args > $max_args ) or ( defined $min_args and $args < $min_args ) ) {
      100        
      100        
1205 2         667 require Error::TypeTiny::WrongNumberOfParameters;
1206 2 50       24 Error::TypeTiny::WrongNumberOfParameters->throw(
    50          
1207             target => "$library\::$type_name\[]",
1208             ( defined $min_args ) ? ( minimum => $min_args ) : (),
1209             ( defined $max_args ) ? ( maximum => $max_args ) : (),
1210             got => $args,
1211             );
1212             }
1213            
1214 929         2629 return;
1215             }
1216              
1217             sub child_type_class {
1218 1524     1524 1 11220 __PACKAGE__;
1219             }
1220              
1221             sub create_child_type {
1222 1524     1524 1 2172552 my $self = shift;
1223 1524         2834 my %moreopts;
1224 1524 100       5720 $moreopts{is_object} = 1 if $self->{is_object};
1225 1524         7305 return $self->child_type_class->new( parent => $self, %moreopts, @_ );
1226             }
1227              
1228             sub complementary_type {
1229 81     81 1 186 my $self = shift;
1230 81   66     487 my $r = ( $self->{complementary_type} ||= $self->_build_complementary_type );
1231             Scalar::Util::weaken( $self->{complementary_type} )
1232 81 100       376 unless Scalar::Util::isweak( $self->{complementary_type} );
1233 81         2059 return $r;
1234             }
1235              
1236             sub _build_complementary_type {
1237 69     69   135 my $self = shift;
1238             my %opts = (
1239 112     112   323 constraint => sub { not $self->check( $_ ) },
1240 69         516 display_name => sprintf( "~%s", $self ),
1241             );
1242 69         252 $opts{display_name} =~ s/^\~{2}//;
1243 309     309   585 $opts{inlined} = sub { shift; "not(" . $self->inline_check( @_ ) . ")" }
  309         940  
1244 69 100       233 if $self->can_be_inlined;
1245             $opts{display_name} = $opts{name} = $self->{complement_name}
1246 69 100       272 if $self->{complement_name};
1247 69         409 return "Type::Tiny"->new( %opts );
1248             } #/ sub _build_complementary_type
1249              
1250             sub _instantiate_moose_type {
1251 0     0   0 my $self = shift;
1252 0         0 my %opts = @_;
1253 0         0 require Moose::Meta::TypeConstraint;
1254 0         0 return "Moose::Meta::TypeConstraint"->new( %opts );
1255             }
1256              
1257             sub _build_moose_type {
1258 0     0   0 my $self = shift;
1259            
1260 0         0 my $r;
1261 0 0       0 if ( $self->{_is_core} ) {
1262 0         0 require Moose::Util::TypeConstraints;
1263 0         0 $r = Moose::Util::TypeConstraints::find_type_constraint( $self->name );
1264 0         0 $r->{"Types::TypeTiny::to_TypeTiny"} = $self;
1265 0         0 Scalar::Util::weaken( $r->{"Types::TypeTiny::to_TypeTiny"} );
1266             }
1267             else {
1268             # Type::Tiny is more flexible than Moose, allowing
1269             # inlined to return a list. So we need to wrap the
1270             # inlined coderef to make sure Moose gets a single
1271             # string.
1272             #
1273             my $wrapped_inlined = sub {
1274 0     0   0 shift;
1275 0         0 $self->inline_check( @_ );
1276 0         0 };
1277            
1278 0         0 my %opts;
1279 0 0 0     0 $opts{name} = $self->qualified_name if $self->has_library && !$self->is_anon;
1280 0 0       0 $opts{parent} = $self->parent->moose_type if $self->has_parent;
1281 0 0       0 $opts{constraint} = $self->constraint unless $self->_is_null_constraint;
1282 0 0       0 $opts{message} = $self->message if $self->has_message;
1283 0 0       0 $opts{inlined} = $wrapped_inlined if $self->has_inlined;
1284            
1285 0         0 $r = $self->_instantiate_moose_type( %opts );
1286 0         0 $r->{"Types::TypeTiny::to_TypeTiny"} = $self;
1287 0         0 $self->{moose_type} = $r; # prevent recursion
1288 0 0       0 $r->coercion( $self->coercion->moose_coercion ) if $self->has_coercion;
1289             } #/ else [ if ( $self->{_is_core})]
1290            
1291 0         0 return $r;
1292             } #/ sub _build_moose_type
1293              
1294             sub _build_mouse_type {
1295 0     0   0 my $self = shift;
1296            
1297 0         0 my %options;
1298 0 0 0     0 $options{name} = $self->qualified_name if $self->has_library && !$self->is_anon;
1299 0 0       0 $options{parent} = $self->parent->mouse_type if $self->has_parent;
1300 0 0       0 $options{constraint} = $self->constraint unless $self->_is_null_constraint;
1301 0 0       0 $options{message} = $self->message if $self->has_message;
1302            
1303 0         0 require Mouse::Meta::TypeConstraint;
1304 0         0 my $r = "Mouse::Meta::TypeConstraint"->new( %options );
1305            
1306 0         0 $self->{mouse_type} = $r; # prevent recursion
1307 0 0       0 $r->_add_type_coercions(
1308             $self->coercion->freeze->_codelike_type_coercion_map( 'mouse_type' ) )
1309             if $self->has_coercion;
1310            
1311 0         0 return $r;
1312             } #/ sub _build_mouse_type
1313              
1314             sub exportables {
1315 15170     15170 1 41633 my ( $self, $base_name, $tag ) = ( shift, @_ ); # $tag is undocumented
1316 15170 100       35679 if ( not $self->is_anon ) {
1317 15169   66     44195 $base_name ||= $self->name;
1318             }
1319 15170   100     64954 $tag ||= 0;
1320              
1321 15170         23607 my @exportables;
1322 15170 50       31526 return \@exportables if ! $base_name;
1323              
1324 15170         103687 require Eval::TypeTiny;
1325              
1326 15170 100 66     90836 push @exportables, {
1327             name => $base_name,
1328             code => Eval::TypeTiny::type_to_coderef( $self ),
1329             tags => [ 'types' ],
1330             } if $tag eq 'types' || !$tag;
1331              
1332 15170 100 100     118938 push @exportables, {
1333             name => sprintf( 'is_%s', $base_name ),
1334             code => $self->compiled_check,
1335             tags => [ 'is' ],
1336             } if $tag eq 'is' || !$tag;
1337              
1338 15170 100 66     96045 push @exportables, {
1339             name => sprintf( 'assert_%s', $base_name ),
1340             code => $self->_overload_coderef,
1341             tags => [ 'assert' ],
1342             } if $tag eq 'assert' || !$tag;
1343              
1344             push @exportables, {
1345             name => sprintf( 'to_%s', $base_name ),
1346             code => $self->has_coercion && $self->coercion->frozen
1347             ? $self->coercion->compiled_coercion
1348 9     9   296374 : sub ($) { $self->coerce( $_[0] ) },
        9      
        18      
        18      
        27      
        27      
        22      
        18      
        18      
        18      
        22      
        18      
        22      
        22      
        23      
        18      
        18      
        27      
        27      
        18      
        18      
        23      
        32      
        32      
        23      
        23      
        28      
        28      
        28      
        28      
        33      
        37      
        38      
        33      
        32      
        32      
        23      
        649      
1349 15170 100 100     117312 tags => [ 'to' ],
    100 100        
1350             } if $tag eq 'to' || !$tag;
1351              
1352 15170         71209 return \@exportables;
1353             }
1354              
1355             sub exportables_by_tag {
1356 785     794 1 2959 my ( $self, $tag, $base_name ) = ( shift, @_ );
1357             my @matched = grep {
1358 785         1720 my $e = $_;
1359 785 50       1473 grep $_ eq $tag, @{ $e->{tags} || [] };
  785         4763  
1360 785         1675 } @{ $self->exportables( $base_name, $tag ) };
  785         2565  
1361 785 100       4493 return @matched if wantarray;
1362 1 50       2 _croak( 'Expected to find one exportable tagged "%s", found %d', $tag, scalar @matched )
1363             unless @matched == 1;
1364 1         2 return $matched[0];
1365             }
1366              
1367             sub _process_coercion_list {
1368 93     98   213 my $self = shift;
1369            
1370 93         177 my @pairs;
1371 93         316 while ( @_ ) {
1372 97         212 my $next = shift;
1373 97 100 66     545 if ( blessed( $next )
    100 100        
    50 66        
1374             and $next->isa( 'Type::Coercion' )
1375             and $next->is_parameterized )
1376             {
1377 7         16 push @pairs => ( @{ $next->_reparameterize( $self )->type_coercion_map } );
  7         21  
1378             }
1379             elsif ( blessed( $next ) and $next->can( 'type_coercion_map' ) ) {
1380             push @pairs => (
1381 9         25 @{ $next->type_coercion_map },
  9         19  
1382             );
1383             }
1384             elsif ( ref( $next ) eq q(ARRAY) ) {
1385 0         0 unshift @_, @$next;
1386             }
1387             else {
1388 81         508 push @pairs => (
1389             Types::TypeTiny::to_TypeTiny( $next ),
1390             shift,
1391             );
1392             }
1393             } #/ while ( @_ )
1394            
1395 93         311 return @pairs;
1396             } #/ sub _process_coercion_list
1397              
1398             sub plus_coercions {
1399 90     90 1 3041900 my $self = shift;
1400 90         472 my $new = $self->_clone;
1401             $new->coercion->add_type_coercions(
1402             $self->_process_coercion_list( @_ ),
1403 90         377 @{ $self->coercion->type_coercion_map },
  90         450  
1404             );
1405 90         334 $new->coercion->freeze;
1406 90         2539 return $new;
1407             } #/ sub plus_coercions
1408              
1409             sub plus_fallback_coercions {
1410 2     2 1 502 my $self = shift;
1411            
1412 2         9 my $new = $self->_clone;
1413             $new->coercion->add_type_coercions(
1414 2         6 @{ $self->coercion->type_coercion_map },
  2         4  
1415             $self->_process_coercion_list( @_ ),
1416             );
1417 2         4 $new->coercion->freeze;
1418 2         4 return $new;
1419             } #/ sub plus_fallback_coercions
1420              
1421             sub minus_coercions {
1422 1     1 1 826 my $self = shift;
1423            
1424 1         6 my $new = $self->_clone;
1425 1         7 my @not = grep Types::TypeTiny::is_TypeTiny( $_ ),
1426             $self->_process_coercion_list( $new, @_ );
1427            
1428 1         7 my @keep;
1429 1         5 my $c = $self->coercion->type_coercion_map;
1430 1         7 for ( my $i = 0 ; $i <= $#$c ; $i += 2 ) {
1431 4         7 my $keep_this = 1;
1432 4         8 NOT: for my $n ( @not ) {
1433 11 100       34 if ( $c->[$i] == $n ) {
1434 2         5 $keep_this = 0;
1435 2         8 last NOT;
1436             }
1437             }
1438            
1439 4 100       22 push @keep, $c->[$i], $c->[ $i + 1 ] if $keep_this;
1440             } #/ for ( my $i = 0 ; $i <=...)
1441            
1442 1         7 $new->coercion->add_type_coercions( @keep );
1443 1         3 $new->coercion->freeze;
1444 1         4 return $new;
1445             } #/ sub minus_coercions
1446              
1447             sub no_coercions {
1448 4     4 1 1626 my $new = shift->_clone;
1449 4         14 $new->coercion->freeze;
1450 4         16 $new;
1451             }
1452              
1453             sub coercibles {
1454 16     16 1 407 my $self = shift;
1455 16 100       79 $self->has_coercion ? $self->coercion->_source_type_union : $self;
1456             }
1457              
1458             sub isa {
1459 282906     282906 1 25524055 my $self = shift;
1460            
1461 282906 0 33     735752 if ( $INC{"Moose/Meta/TypeConstraint.pm"}
      33        
1462             and ref( $self )
1463             and $_[0] =~ /^(?:Class::MOP|MooseX?::Meta)::(.+)$/ )
1464             {
1465 0         0 my $meta = $1;
1466            
1467 0 0       0 return !!1 if $meta eq 'TypeConstraint';
1468 0 0       0 return $self->is_parameterized if $meta eq 'TypeConstraint::Parameterized';
1469 0 0       0 return $self->is_parameterizable if $meta eq 'TypeConstraint::Parameterizable';
1470 0 0       0 return $self->isa( 'Type::Tiny::Union' ) if $meta eq 'TypeConstraint::Union';
1471            
1472 0         0 my $inflate = $self->moose_type;
1473 0         0 return $inflate->isa( @_ );
1474             } #/ if ( $INC{"Moose/Meta/TypeConstraint.pm"} ...)
1475            
1476 282906 0 33     729668 if ( $INC{"Mouse.pm"}
      33        
1477             and ref( $self )
1478             and $_[0] eq 'Mouse::Meta::TypeConstraint' )
1479             {
1480 0         0 return !!1;
1481             }
1482            
1483 282906         1567482 $self->SUPER::isa( @_ );
1484             } #/ sub isa
1485              
1486             sub _build_my_methods {
1487 158     158   1000 return {};
1488             }
1489              
1490             sub _lookup_my_method {
1491 1330     1330   2092 my $self = shift;
1492 1330         3478 my ( $name ) = @_;
1493            
1494 1330 100       3163 if ( $self->my_methods->{$name} ) {
1495 640         1309 return $self->my_methods->{$name};
1496             }
1497            
1498 690 100       1711 if ( $self->has_parent ) {
1499 688         1609 return $self->parent->_lookup_my_method( @_ );
1500             }
1501            
1502 2         12 return;
1503             } #/ sub _lookup_my_method
1504              
1505             my %object_methods = (
1506             with_attribute_values => 1, stringifies_to => 1,
1507             numifies_to => 1
1508             );
1509              
1510             my $re_list_methods = qr/\A(?:(?:a(?:ll|ny|ssert_a(?:ll|ny))|first|grep|map|rsort|sort))\z/;
1511              
1512             sub can {
1513 83200     83200 1 413892 my $self = shift;
1514            
1515 83200 50 66     231950 return !!0
      33        
1516             if $_[0] eq 'type_parameter'
1517             && blessed( $_[0] )
1518             && $_[0]->has_parameters;
1519            
1520 83200         324514 my $can = $self->SUPER::can( @_ );
1521 83200 100       879366 return $can if $can;
1522            
1523 42361 100       109238 if ( ref( $self ) ) {
1524 42360 100       123186 if ( $_[0] =~ /\Amy_(.+)\z/ ) {
1525 4         34 my $method = $self->_lookup_my_method( $1 );
1526 4 100       15 return $method if $method;
1527             }
1528 42358 100 100     144307 if ( $self->{is_object} && $object_methods{ $_[0] } ) {
1529 1         981 require Type::Tiny::ConstrainedObject;
1530 1         17 return Type::Tiny::ConstrainedObject->can( $_[0] );
1531             }
1532 42357 100       322510 if ( $_[0] =~ $re_list_methods ) {
1533 36         57 my $util = $_[0];
1534 36   66     126 $self->{'_util'}{$util} ||= eval { $self->_build_util( $util ) };
  36         75  
1535 36 100       131 return unless $self->{'_util'}{$util};
1536 34     0   155 return sub { my $s = shift; $s->{'_util'}{$util}( @_ ) };
  0         0  
  0         0  
1537             }
1538 42321 50       120203 if ( $INC{"Moose/Meta/TypeConstraint.pm"} ) {
1539 0         0 my $method = $self->moose_type->can( @_ );
1540 0     0   0 return sub { shift->moose_type->$method( @_ ) }
1541 0 0       0 if $method;
1542             }
1543             } #/ if ( ref( $self ) )
1544            
1545 42322         323485 return;
1546             } #/ sub can
1547              
1548             sub AUTOLOAD {
1549 1859     1859   29500 my $self = shift;
1550 1859         15159 my ( $m ) = ( our $AUTOLOAD =~ /::(\w+)$/ );
1551 1859 50       6149 return if $m eq 'DESTROY';
1552            
1553 1859 50       5266 if ( ref( $self ) ) {
1554 1859 100       5327 if ( $m =~ /\Amy_(.+)\z/ ) {
1555 638         2258 my $method = $self->_lookup_my_method( $1 );
1556 638 50       3131 return &$method( $self, @_ ) if $method;
1557             }
1558 1221 50 66     5237 if ( $self->{is_object} && $object_methods{$m} ) {
1559 3         1284 require Type::Tiny::ConstrainedObject;
1560 3         12 unshift @_, $self;
1561 310     310   4037 no strict 'refs';
  310         718  
  310         543693  
1562 3         7 goto \&{"Type::Tiny::ConstrainedObject::$m"};
  3         27  
1563             }
1564 1218 100       10465 if ( $m =~ $re_list_methods ) {
1565 1217   66     38706 return ( $self->{'_util'}{$m} ||= $self->_build_util( $m ) )->( @_ );
1566             }
1567 1 50       5 if ( $INC{"Moose/Meta/TypeConstraint.pm"} ) {
1568 0         0 my $method = $self->moose_type->can( $m );
1569 0 0       0 return $self->moose_type->$method( @_ ) if $method;
1570             }
1571             } #/ if ( ref( $self ) )
1572            
1573 1   33     8 _croak q[Can't locate object method "%s" via package "%s"], $m,
1574             ref( $self ) || $self;
1575             } #/ sub AUTOLOAD
1576              
1577             sub DOES {
1578 45     45 1 103 my $self = shift;
1579            
1580 45 50 33     197 return !!1
1581             if ref( $self )
1582             && $_[0] =~ m{^ Type::API::Constraint (?: ::Coercible | ::Inlinable )? $}x;
1583 45 50 33     109 return !!1 if !ref( $self ) && $_[0] eq 'Type::API::Constraint::Constructor';
1584            
1585 45 50       332 "UNIVERSAL"->can( "DOES" ) ? $self->SUPER::DOES( @_ ) : $self->isa( @_ );
1586             } #/ sub DOES
1587              
1588             sub _has_xsub {
1589 1     1   880 require B;
1590 1         6 !!B::svref_2object( shift->compiled_check )->XSUB;
1591             }
1592              
1593             sub _build_util {
1594 218     218   604 my ( $self, $func ) = @_;
1595 218         598 Scalar::Util::weaken( my $type = $self );
1596            
1597 218 100 100     2333 if ( $func eq 'grep'
      100        
      100        
      100        
      100        
1598             || $func eq 'first'
1599             || $func eq 'any'
1600             || $func eq 'all'
1601             || $func eq 'assert_any'
1602             || $func eq 'assert_all' )
1603             {
1604 179         358 my ( $inline, $compiled );
1605            
1606 179 100       829 if ( $self->can_be_inlined ) {
1607 149         608 $inline = $self->inline_check( '$_' );
1608             }
1609             else {
1610 30         58 $compiled = $self->compiled_check;
1611 30         53 $inline = '$compiled->($_)';
1612             }
1613            
1614 179 100       1434 if ( $func eq 'grep' ) {
    100          
    100          
    100          
    100          
    50          
1615 10         908 return eval "sub { grep { $inline } \@_ }";
1616             }
1617             elsif ( $func eq 'first' ) {
1618 5         594 return eval "sub { for (\@_) { return \$_ if ($inline) }; undef; }";
1619             }
1620             elsif ( $func eq 'any' ) {
1621 8         874 return eval "sub { for (\@_) { return !!1 if ($inline) }; !!0; }";
1622             }
1623             elsif ( $func eq 'assert_any' ) {
1624 8         19 my $qname = B::perlstring( $self->name );
1625             return
1626             eval
1627 8         1305 "sub { for (\@_) { return \@_ if ($inline) }; Type::Tiny::_failed_check(\$type, $qname, \@_ ? \$_[-1] : undef); }";
1628             }
1629             elsif ( $func eq 'all' ) {
1630 140         25496 return eval "sub { for (\@_) { return !!0 unless ($inline) }; !!1; }";
1631             }
1632             elsif ( $func eq 'assert_all' ) {
1633 8         18 my $qname = B::perlstring( $self->name );
1634             return
1635             eval
1636 8         1161 "sub { my \$idx = 0; for (\@_) { Type::Tiny::_failed_check(\$type, $qname, \$_, varname => sprintf('\$_[%d]', \$idx)) unless ($inline); ++\$idx }; \@_; }";
1637             }
1638             } #/ if ( $func eq 'grep' ||...)
1639            
1640 39 100       86 if ( $func eq 'map' ) {
1641 8         12 my ( $inline, $compiled );
1642 8         16 my $c = $self->_assert_coercion;
1643            
1644 4 100       10 if ( $c->can_be_inlined ) {
1645 1         4 $inline = $c->inline_coercion( '$_' );
1646             }
1647             else {
1648 3         12 $compiled = $c->compiled_coercion;
1649 3         10 $inline = '$compiled->($_)';
1650             }
1651            
1652 4         450 return eval "sub { map { $inline } \@_ }";
1653             } #/ if ( $func eq 'map' )
1654            
1655 31 100 100     99 if ( $func eq 'sort' || $func eq 'rsort' ) {
1656 29         47 my ( $inline, $compiled );
1657            
1658 29     76   167 my $ptype = $self->find_parent( sub { $_->has_sorter } );
  76         148  
1659 29 100       108 _croak "No sorter for this type constraint" unless $ptype;
1660            
1661 27         109 my $sorter = $ptype->sorter;
1662            
1663             # Schwarzian transformation
1664 27 100       76 if ( ref( $sorter ) eq 'ARRAY' ) {
1665 6         8 my $sort_key;
1666 6         41 ( $sorter, $sort_key ) = @$sorter;
1667            
1668 6 100       22 if ( $func eq 'sort' ) {
    50          
1669             return
1670             eval
1671 4         701 "our (\$a, \$b); sub { map \$_->[0], sort { \$sorter->(\$a->[1],\$b->[1]) } map [\$_,\$sort_key->(\$_)], \@_ }";
1672             }
1673             elsif ( $func eq 'rsort' ) {
1674             return
1675             eval
1676 2         289 "our (\$a, \$b); sub { map \$_->[0], sort { \$sorter->(\$b->[1],\$a->[1]) } map [\$_,\$sort_key->(\$_)], \@_ }";
1677             }
1678             } #/ if ( ref( $sorter ) eq...)
1679            
1680             # Simple sort
1681             else {
1682 21 100       50 if ( $func eq 'sort' ) {
    50          
1683 12         1600 return eval "our (\$a, \$b); sub { sort { \$sorter->(\$a,\$b) } \@_ }";
1684             }
1685             elsif ( $func eq 'rsort' ) {
1686 9         1082 return eval "our (\$a, \$b); sub { sort { \$sorter->(\$b,\$a) } \@_ }";
1687             }
1688             }
1689             } #/ if ( $func eq 'sort' ||...)
1690            
1691 2         16 die "Unknown function: $func";
1692             } #/ sub _build_util
1693              
1694 341     341 1 1519527 sub of { shift->parameterize( @_ ) }
1695 142     142 1 1034875 sub where { shift->create_child_type( constraint => @_ ) }
1696              
1697             # fill out Moose-compatible API
1698 1     1 1 324066 sub inline_environment { +{} }
1699 1     1   10 sub _inline_check { shift->inline_check( @_ ) }
1700 2     2   387 sub _compiled_type_constraint { shift->compiled_check( @_ ) }
1701 1     1 1 17 sub meta { _croak( "Not really a Moose::Meta::TypeConstraint. Sorry!" ) }
1702 2     2 1 14 sub compile_type_constraint { shift->compiled_check }
1703 2     2   21 sub _actually_compile_type_constraint { shift->_build_compiled_check }
1704 1     1 1 589 sub hand_optimized_type_constraint { shift->{hand_optimized_type_constraint} }
1705              
1706             sub has_hand_optimized_type_constraint {
1707 1     1 1 11 exists( shift->{hand_optimized_type_constraint} );
1708             }
1709 218   50 218 1 1985 sub type_parameter { ( shift->parameters || [] )->[0] }
1710              
1711             sub parameterized_from {
1712 5 50   5 1 27 $_[0]->is_parameterized ? shift->parent : _croak( "Not a parameterized type" );
1713             }
1714 2     2 1 10 sub has_parameterized_from { $_[0]->is_parameterized }
1715              
1716             # some stuff for Mouse-compatible API
1717 2     2   13 sub __is_parameterized { shift->is_parameterized( @_ ) }
1718 1     1   10 sub _add_type_coercions { shift->coercion->add_type_coercions( @_ ) }
1719 1     1   967 sub _as_string { shift->qualified_name( @_ ) }
1720 1     1   4 sub _compiled_type_coercion { shift->coercion->compiled_coercion( @_ ) }
1721 2     2   982 sub _identity { Scalar::Util::refaddr( shift ) }
1722              
1723             sub _unite {
1724 1     1   468 require Type::Tiny::Union;
1725 1         5 "Type::Tiny::Union"->new( type_constraints => \@_ );
1726             }
1727              
1728             # Hooks for Type::Tie
1729             sub TIESCALAR {
1730 3     3   850771 require Type::Tie;
1731 3         21 unshift @_, 'Type::Tie::SCALAR';
1732 3         44 goto \&Type::Tie::SCALAR::TIESCALAR;
1733             }
1734              
1735             sub TIEARRAY {
1736 2     2   6958 require Type::Tie;
1737 2         9 unshift @_, 'Type::Tie::ARRAY';
1738 2         13 goto \&Type::Tie::ARRAY::TIEARRAY;
1739             }
1740              
1741             sub TIEHASH {
1742 2     2   5059 require Type::Tie;
1743 2         11 unshift @_, 'Type::Tie::HASH';
1744 2         12 goto \&Type::Tie::HASH::TIEHASH;
1745             }
1746              
1747             1;
1748              
1749             __END__