bool => sub { 1 },
fallback => 1;
+use Eval::Closure;
use Scalar::Util qw(blessed refaddr);
use Sub::Name qw(subname);
use Try::Tiny;
predicate => '_has_inlined_type_constraint',
));
+__PACKAGE__->meta->add_attribute('inline_environment' => (
+ init_arg => 'inline_environment',
+ accessor => '_inline_environment',
+ default => sub { {} },
+));
+
sub parents {
my $self;
$self->parent;
}
}
-sub has_inlined_type_constraint {
+sub can_be_inlined {
my $self = shift;
if ( $self->has_parent && $self->constraint == $null_constraint ) {
- return $self->parent->has_inlined_type_constraint;
+ return $self->parent->can_be_inlined;
}
return $self->_has_inlined_type_constraint;
sub _inline_check {
my $self = shift;
- unless ( $self->has_inlined_type_constraint ) {
+ unless ( $self->can_be_inlined ) {
require Moose;
Moose->throw_error( 'Cannot inline a type constraint check for ' . $self->name );
}
return $self->parent->_inline_check(@_);
}
- return $self->inlined->( $self, @_ );
+ return '( do { ' . $self->inlined->( $self, @_ ) . ' } )';
+}
+
+sub inline_environment {
+ my $self = shift;
+
+ if ( $self->has_parent && $self->constraint == $null_constraint ) {
+ return $self->parent->inline_environment;
+ }
+
+ return $self->_inline_environment;
}
sub assert_valid {
return $self->_compile_hand_optimized_type_constraint
if $self->has_hand_optimized_type_constraint;
- if ( $self->has_inlined_type_constraint ) {
- local $@;
- my $sub = eval 'sub { ' . $self->_inline_check('$_[0]') . '}';
- die $@ if $@;
-
- return $sub;
+ if ( $self->can_be_inlined ) {
+ return eval_closure(
+ source => 'sub { ' . $self->_inline_check('$_[0]') . ' }',
+ environment => $self->inline_environment,
+ );
}
my $check = $self->constraint;
A L<Moose::Meta::TypeCoercion> object representing the coercions to
the type. This is optional.
+=item * inlined
+
+A subroutine which returns a string suitable for inlining this type
+constraint. It will be called as a method on the type constraint object, and
+will receive a single additional parameter, a variable name to be tested
+(usually C<"$_"> or C<"$_[0]">.
+
+This is optional.
+
+=item * inline_environment
+
+A hash reference of variables to close over. The keys are variables names, and
+the values are I<references> to the variables.
+
=item * optimized
+B<This option is deprecated.>
+
This is a variant of the C<constraint> parameter that is somehow
optimized. Typically, this means incorporating both the type's
constraint and all of its parents' constraints into a single
Returns true if the type has a coercion.
+=item B<< $constraint->can_be_inlined >>
+
+Returns true if this type constraint can be inlined. A type constraint which
+subtypes an inlinable constraint and does not add an additional constraint
+"inherits" its parent type's inlining.
+
=item B<< $constraint->hand_optimized_type_constraint >>
+B<This method is deprecated.>
+
Returns the type's hand optimized constraint, as provided to the
constructor via the C<optimized> option.
=item B<< $constraint->has_hand_optimized_type_constraint >>
+B<This method is deprecated.>
+
Returns true if the type has an optimized constraint.
=item B<< $constraint->create_child_type(%options) >>