RT#83929: fix memory leak in union types
[gitmo/Moose.git] / lib / Moose / Meta / TypeConstraint / DuckType.pm
CommitLineData
0a6bff54 1package Moose::Meta::TypeConstraint::DuckType;
2
3use strict;
4use warnings;
5use metaclass;
6
964294c1 7use B;
42af2755 8use Scalar::Util 'blessed';
0a6bff54 9use List::MoreUtils qw(all);
10use Moose::Util 'english_list';
11
12use Moose::Util::TypeConstraints ();
13
0a6bff54 14use base 'Moose::Meta::TypeConstraint';
15
16__PACKAGE__->meta->add_attribute('methods' => (
17 accessor => 'methods',
dc2b7cc8 18 Class::MOP::_definition_context(),
0a6bff54 19));
20
964294c1 21my $inliner = sub {
22 my $self = shift;
23 my $val = shift;
24
4f073d2d 25 return $self->parent->_inline_check($val)
26 . ' && do {' . "\n"
27 . 'my $val = ' . $val . ';' . "\n"
28 . '&List::MoreUtils::all(' . "\n"
29 . 'sub { $val->can($_) },' . "\n"
3975b592 30 . join(', ', map { B::perlstring($_) } @{ $self->methods })
4f073d2d 31 . ');' . "\n"
32 . '}';
964294c1 33};
34
0a6bff54 35sub new {
36 my ( $class, %args ) = @_;
37
964294c1 38 $args{parent}
39 = Moose::Util::TypeConstraints::find_type_constraint('Object');
40
41 my @methods = @{ $args{methods} };
42 $args{constraint} = sub {
21ddc881 43 my $val = $_[0];
4f073d2d 44 return all { $val->can($_) } @methods;
964294c1 45 };
46
47 $args{inlined} = $inliner;
0a6bff54 48
92a88343 49 my $self = $class->SUPER::new(\%args);
0a6bff54 50
51 $self->compile_type_constraint()
52 unless $self->_has_compiled_type_constraint;
53
54 return $self;
55}
56
57sub equals {
58 my ( $self, $type_or_name ) = @_;
59
60 my $other = Moose::Util::TypeConstraints::find_type_constraint($type_or_name);
61
62 return unless $other->isa(__PACKAGE__);
63
64 my @self_methods = sort @{ $self->methods };
65 my @other_methods = sort @{ $other->methods };
66
67 return unless @self_methods == @other_methods;
68
69 while ( @self_methods ) {
70 my $method = shift @self_methods;
71 my $other_method = shift @other_methods;
72
73 return unless $method eq $other_method;
74 }
75
76 return 1;
77}
78
0a6bff54 79sub create_child_type {
80 my ($self, @args) = @_;
81 return Moose::Meta::TypeConstraint->new(@args, parent => $self);
82}
83
84sub get_message {
85 my $self = shift;
86 my ($value) = @_;
87
88 if ($self->has_message) {
89 return $self->SUPER::get_message(@_);
90 }
91
6ea852f8 92 return $self->SUPER::get_message($value) unless blessed($value);
93
0a6bff54 94 my @methods = grep { !$value->can($_) } @{ $self->methods };
95 my $class = blessed $value;
d9f45e2e 96 $class ||= $value;
97
0a6bff54 98 return $class
99 . " is missing methods "
100 . english_list(map { "'$_'" } @methods);
101}
102
1031;
104
ad46f524 105# ABSTRACT: Type constraint for duck typing
106
0a6bff54 107__END__
108
109=pod
110
0a6bff54 111=head1 DESCRIPTION
112
113This class represents type constraints based on an enumerated list of
114required methods.
115
116=head1 INHERITANCE
117
118C<Moose::Meta::TypeConstraint::DuckType> is a subclass of
119L<Moose::Meta::TypeConstraint>.
120
121=head1 METHODS
122
123=over 4
124
125=item B<< Moose::Meta::TypeConstraint::DuckType->new(%options) >>
126
127This creates a new duck type constraint based on the given
128C<%options>.
129
130It takes the same options as its parent, with several
131exceptions. First, it requires an additional option, C<methods>. This
132should be an array reference containing a list of required method
133names. Second, it automatically sets the parent to the C<Object> type.
134
135Finally, it ignores any provided C<constraint> option. The constraint
136is generated automatically based on the provided C<methods>.
137
138=item B<< $constraint->methods >>
139
140Returns the array reference of required methods provided to the
141constructor.
142
143=item B<< $constraint->create_child_type >>
144
145This returns a new L<Moose::Meta::TypeConstraint> object with the type
146as its parent.
147
148Note that it does I<not> return a C<Moose::Meta::TypeConstraint::DuckType>
149object!
150
151=back
152
153=head1 BUGS
154
d4048ef3 155See L<Moose/BUGS> for details on reporting bugs.
0a6bff54 156
0a6bff54 157=cut
158