Wrap all TC inlining in parens and a do { } block
Dave Rolsky [Mon, 25 Apr 2011 01:57:10 +0000 (20:57 -0500)]
The parens protect against precedence issues when being used with logical operators.

The do { } block provides each TC its own scope, so that if it defines variables they don't leak out to the enclosing code.

lib/Moose/Meta/TypeConstraint.pm
lib/Moose/Meta/TypeConstraint/Parameterizable.pm
lib/Moose/Util/TypeConstraints/Builtins.pm
t/type_constraints/inlining.t

index d500356..303b8fb 100644 (file)
@@ -157,7 +157,7 @@ sub _inline_check {
         return $self->parent->_inline_check(@_);
     }
 
-    return $self->inlined->( $self, @_ );
+    return '( do { ' . $self->inlined->( $self, @_ ) . ' } )';
 }
 
 sub inline_environment {
index 584b909..a5b9052 100644 (file)
@@ -52,7 +52,7 @@ sub generate_inline_for {
           . "was defined"
         unless $self->has_inline_generator;
 
-    return $self->inline_generator->( $self, $type, $val );
+    return '( do { ' . $self->inline_generator->( $self, $type, $val ) . ' } )';
 }
 
 sub _parse_type_parameter {
index 7beac71..e558755 100644 (file)
@@ -60,7 +60,7 @@ sub define_builtins {
         => inline_as {
             'defined(' . $_[1] . ') '
               . '&& (ref(\\' . $_[1] . ') eq "SCALAR"'
-              . '|| do { ref(\\(my $val = ' . $_[1] . ')) eq "SCALAR" })'
+              . '|| ref(\\(my $val = ' . $_[1] . ')) eq "SCALAR" )'
         };
 
     subtype 'Num'
@@ -77,7 +77,7 @@ sub define_builtins {
         => inline_as {
             'defined(' . $_[1] . ') '
               . '&& !ref(' . $_[1] . ') '
-              . '&& do { (my $val = ' . $_[1] . ') =~ /\A-?[0-9]+\z/ }'
+              . '&& (my $val = ' . $_[1] . ') =~ /\A-?[0-9]+\z/'
         };
 
     subtype 'CodeRef'
index cdc4a21..d096e69 100644 (file)
@@ -30,7 +30,7 @@ my $not_inlinable = find_type_constraint('NotInlinable');
 
     is(
         $inlinable->_inline_check('$foo'),
-        'defined $foo && ! ref $foo && $foo !~ /Q/',
+        '( do { defined $foo && ! ref $foo && $foo !~ /Q/ } )',
         'got expected inline code for Inlinable constraint'
     );
 
@@ -57,7 +57,7 @@ my $not_inlinable = find_type_constraint('NotInlinable');
 
     is(
         $aofi->_inline_check('$foo'),
-        q{do {my $check = $foo;ref($check) eq "ARRAY" && &List::MoreUtils::all(sub { defined $_ && ! ref $_ && $_ !~ /Q/ }, @{$check})}},
+        q{( do { do {my $check = $foo;ref($check) eq "ARRAY" && &List::MoreUtils::all(sub { ( do { defined $_ && ! ref $_ && $_ !~ /Q/ } ) }, @{$check})} } )},
         'got expected inline code for ArrayRef[Inlinable] constraint'
     );
 
@@ -86,7 +86,7 @@ subtype 'ArrayOfNotInlinable',
 
     is(
         $aofi->_inline_check('$foo'),
-        q{do {my $check = $foo;ref($check) eq "ARRAY" && &List::MoreUtils::all(sub { defined $_ && ! ref $_ && $_ !~ /Q/ }, @{$check})}},
+        q{( do { do {my $check = $foo;ref($check) eq "ARRAY" && &List::MoreUtils::all(sub { ( do { defined $_ && ! ref $_ && $_ !~ /Q/ } ) }, @{$check})} } )},
         'got expected inline code for ArrayOfInlinable constraint'
     );
 
@@ -110,7 +110,7 @@ subtype 'ArrayOfNotInlinable',
 
     is(
         $hoaofi->_inline_check('$foo'),
-        q{do {my $check = $foo;ref($check) eq "HASH" && &List::MoreUtils::all(sub { do {my $check = $_;ref($check) eq "ARRAY" && &List::MoreUtils::all(sub { defined $_ && ! ref $_ && $_ !~ /Q/ }, @{$check})} }, values %{$check})}},
+        q{( do { do {my $check = $foo;ref($check) eq "HASH" && &List::MoreUtils::all(sub { ( do { do {my $check = $_;ref($check) eq "ARRAY" && &List::MoreUtils::all(sub { ( do { defined $_ && ! ref $_ && $_ !~ /Q/ } ) }, @{$check})} } ) }, values %{$check})} } )},
         'got expected inline code for HashRef[ArrayRef[Inlinable]] constraint'
     );
 
@@ -134,7 +134,7 @@ subtype 'ArrayOfNotInlinable',
 
     is(
         $iunion->_inline_check('$foo'),
-        '(defined $foo && ! ref $foo && $foo !~ /Q/) || (Scalar::Util::blessed($foo))',
+        '((( do { defined $foo && ! ref $foo && $foo !~ /Q/ } )) || (( do { Scalar::Util::blessed($foo) } )))',
         'got expected inline code for Inlinable | Object constraint'
     );
 
@@ -158,7 +158,7 @@ subtype 'ArrayOfNotInlinable',
 
     is(
         $iunion->_inline_check('$foo'),
-        '(Scalar::Util::blessed($foo)) || (defined $foo && ! ref $foo && $foo !~ /Q/)',
+        '((( do { Scalar::Util::blessed($foo) } )) || (( do { defined $foo && ! ref $foo && $foo !~ /Q/ } )))',
         'got expected inline code for Object | Inlinable constraint'
     );
 
@@ -182,7 +182,7 @@ subtype 'ArrayOfNotInlinable',
 
     is(
         $iunion->_inline_check('$foo'),
-        q{(Scalar::Util::blessed($foo)) || (defined $foo && ! ref $foo && $foo !~ /Q/) || (ref($foo) eq "CODE")},
+        q{((( do { Scalar::Util::blessed($foo) } )) || (( do { defined $foo && ! ref $foo && $foo !~ /Q/ } )) || (( do { ref($foo) eq "CODE" } )))},
         'got expected inline code for Object | Inlinable | CodeRef constraint'
     );