From 1c9754bec322cc5f7b7bf6eaac7389b3ccd11f2f Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Fri, 2 Jun 2017 13:19:08 -0700 Subject: [PATCH 1/2] Revert "revert the Sub::Defer changes again temporarily (see RT#119534, RT#120129)" This reverts commit c8f752ef3cb00d514530892c7dad52cdf89d69bc. --- lib/MooseX/Types.pm | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/MooseX/Types.pm b/lib/MooseX/Types.pm index 0988f43..8175bd6 100644 --- a/lib/MooseX/Types.pm +++ b/lib/MooseX/Types.pm @@ -12,6 +12,7 @@ use MooseX::Types::Util qw( filter_tags ); use MooseX::Types::UndefinedType; use MooseX::Types::CheckedUtilExports (); use Carp::Clan qw( ^MooseX::Types ); +use Sub::Defer qw( defer_sub ); use Sub::Name; use Scalar::Util qw( reftype ); use Sub::Exporter::ForMethods 0.100052 'method_installer'; # for 'rebless' @@ -486,17 +487,20 @@ This generates a coercion handler function, e.g. C. sub coercion_export_generator { my ($class, $type, $full, $undef_msg) = @_; - return sub { + return defer_sub undef, sub { my ($value) = @_; # we need a type object my $tobj = find_type_constraint($full) or croak $undef_msg; - my $return = $tobj->coerce($value); - # non-successful coercion returns false - return unless $tobj->check($return); + return sub { + my $return = $tobj->coerce($_[0]); - return $return; + # non-successful coercion returns false + return unless $tobj->check($return); + + return $return; + }; } } @@ -508,13 +512,16 @@ Generates a constraint check closure, e.g. C. sub check_export_generator { my ($class, $type, $full, $undef_msg) = @_; - return sub { + + return defer_sub undef, sub { my ($value) = @_; # we need a type object my $tobj = find_type_constraint($full) or croak $undef_msg; - return $tobj->check($value); + # This method will actually compile an inlined sub if possible. If + # not, it will return something like sub { $tobj->check($_[0]) } + return $tobj->_compiled_type_constraint; } } From 83727f25f776bea797c0d36edd4cd9de28040029 Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Fri, 2 Jun 2017 14:59:22 -0700 Subject: [PATCH 2/2] Delay croaking until use. Fixes RT #119534. This is to maintain compatibility with modules that declare types but never use them. In 0.49, this could cause an exception if Sub::Defer::undefer_all was called. --- Changes | 5 ++++- lib/MooseX/Types.pm | 12 +++++++++--- t/27-sub-defer.t | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 t/27-sub-defer.t diff --git a/Changes b/Changes index e901190..c672347 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,9 @@ Revision history for MooseX-Types {{$NEXT}} + - re-added the is_Foo and to_Food refactoring after resolving + RT #119534 + 0.50 2017-02-07 18:59:30Z - reverted the is_Foo and to_Foo refactoring again temporarily to resolve issues with Sub::Defer @@ -9,7 +12,7 @@ Revision history for MooseX-Types 0.49 2016-12-23 00:12:12Z - made the exported is_Foo and to_Foo subs much faster, especially for type constraints which can be inlined. (Dave Rolsky) [reverted in - 0.50) + 0.50] 0.48 2016-12-07 01:15:14Z - reverted is_Foo and to_Foo refactoring [from 0.47] for now, so they diff --git a/lib/MooseX/Types.pm b/lib/MooseX/Types.pm index 8175bd6..bdd2c36 100644 --- a/lib/MooseX/Types.pm +++ b/lib/MooseX/Types.pm @@ -491,9 +491,11 @@ sub coercion_export_generator { my ($value) = @_; # we need a type object - my $tobj = find_type_constraint($full) or croak $undef_msg; + my $tobj = find_type_constraint($full); return sub { + croak $undef_msg unless $tobj; + my $return = $tobj->coerce($_[0]); # non-successful coercion returns false @@ -517,11 +519,15 @@ sub check_export_generator { my ($value) = @_; # we need a type object - my $tobj = find_type_constraint($full) or croak $undef_msg; + my $tobj = find_type_constraint($full); # This method will actually compile an inlined sub if possible. If # not, it will return something like sub { $tobj->check($_[0]) } - return $tobj->_compiled_type_constraint; + # + # If $tobj is undef, we delay the croaking until the check is + # actually used for backward compatibility reasons. See + # RT #119534. + return $tobj ? $tobj->_compiled_type_constraint : sub { croak $undef_msg}; } } diff --git a/t/27-sub-defer.t b/t/27-sub-defer.t new file mode 100644 index 0000000..70c2c9a --- /dev/null +++ b/t/27-sub-defer.t @@ -0,0 +1,35 @@ +use strict; +use warnings; + +use Test::More 0.88; +use if $ENV{AUTHOR_TESTING}, 'Test::Warnings'; + +use Test::Fatal; +use B::Deparse; +use MooseX::Types::Moose qw( Int ); +use Sub::Defer qw( undefer_all ); + +like( + B::Deparse->new->coderef2text( \&is_Int ), + qr/package Sub::Defer/, + 'is_Int sub has not yet been undeferred' +); +is( + exception { undefer_all() }, + undef, + 'Sub::Defer::undefer_all works with subs exported by MooseX::Types' +); + +{ + package MyTypes; + + use MooseX::Types -declare => ['Unused']; +} + +is( + exception { undefer_all() }, + undef, + 'Sub::Defer::undefer_all does not throw an exception with unused type declaration' +); + +done_testing();