inlining for overloaded object isa/coerce
Toby Inkster [Fri, 5 Apr 2013 17:56:39 +0000 (18:56 +0100)]
lib/Method/Generate/Accessor.pm
t/overloaded-coderefs.t [new file with mode: 0644]

index e5ca31d..135ec69 100644 (file)
@@ -389,6 +389,7 @@ sub _generate_isa_check {
 
 sub _generate_call_code {
   my ($self, $name, $type, $values, $sub) = @_;
+  $sub = \&{$sub} if blessed($sub);  # coderef if blessed
   if (my $quoted = quoted_from_sub($sub)) {
     my $code = $quoted->[1];
     if (my $captures = $quoted->[2]) {
diff --git a/t/overloaded-coderefs.t b/t/overloaded-coderefs.t
new file mode 100644 (file)
index 0000000..c4b1d6b
--- /dev/null
@@ -0,0 +1,54 @@
+use strict;
+use warnings;
+use Test::More;
+
+{
+       package Dark::Side;
+       use overload
+               q[&{}]   => sub { shift->to_code },
+               fallback => 1;
+       sub new {
+               my $class = shift;
+               bless \$_[0], $class;
+       }
+       sub to_code {
+               my $self = shift;
+               eval "sub { $$self }";
+       }
+}
+
+{
+       package The::Force;
+       use Sub::Quote;
+       use base 'Dark::Side';
+       sub to_code {
+               my $self = shift;
+               return quote_sub $$self;
+       }
+}
+
+my $darkside = Dark::Side->new('my $dummy = "join the dark side"; $_[0] * 2');
+is($darkside->(6), 12, 'check Dark::Side coderef');
+
+my $theforce = The::Force->new('my $dummy = "use the force Luke"; $_[0] * 2');
+is($theforce->(6), 12, 'check The::Force coderef');
+
+{
+       package Doubleena;
+       use Moo;
+       has a => (is => "ro", coerce => $darkside, isa => sub { 1 });
+       has b => (is => "ro", coerce => $theforce, isa => The::Force->new('my $z = "I am your father"'));
+}
+
+my $o = Doubleena->new(a => 11, b => 12);
+is($o->a, 22, 'non-Sub::Quoted inlined coercion overload works');
+is($o->b, 24, 'Sub::Quoted inlined coercion overload works');
+
+use B::Deparse;
+my $constructor = B::Deparse->new->coderef2text(Doubleena->can('new'));
+
+like($constructor, qr{use the force Luke}, 'Sub::Quoted coercion got inlined');
+unlike($constructor, qr{join the dark side}, 'non-Sub::Quoted coercion was not inlined');
+like($constructor, qr{I am your father}, 'Sub::Quoted isa got inlined');
+
+done_testing;