The last checkin was broken in the case where class B inherited from
Dave Rolsky [Thu, 4 Dec 2008 22:39:05 +0000 (22:39 +0000)]
class A, and class A had made itself immutable.

In that case, MMMC thought that the inlined constructor for A meant it
couldn't inline for B. This checkin fixes it to be much smarter. If
any parent is inlined, it checks to see if the inlined constructor's
class in the parent matches the constructor class that's trying to do
inlining. If they match, it goes ahead and inlines, otherwise it
doesn't.

lib/Moose/Meta/Method/Constructor.pm
t/300_immutable/010_constructor_is_not_moose.t

index 83347ba..4873c8b 100644 (file)
@@ -51,6 +51,20 @@ sub can_be_inlined {
     my $self      = shift;
     my $metaclass = $self->associated_metaclass;
 
+    # If any of our parents have been made immutable, we are okay to
+    # inline our own method as long as the parent's constructor class
+    # is the same as $self.
+    for my $meta ( grep { $_->is_immutable }
+        map { ( ref $metaclass )->initialize($_) }
+        $metaclass->linearized_isa ) {
+        my $transformer = $meta->get_immutable_transformer;
+
+        my $constructor = $transformer->inlined_constructor
+            or next;
+
+        return ref $constructor eq ref $self;
+    }
+
     if ( my $constructor = $metaclass->find_method_by_name( $self->name ) ) {
 
         my $expected_class = $self->_expected_constructor_class;
index 948c35f..2a03b24 100644 (file)
@@ -8,7 +8,7 @@ use Test::More;
 eval "use Test::Output";
 plan skip_all => "Test::Output is required for this test" if $@;
 
-plan tests => 4;
+plan tests => 5;
 
 {
     package NotMoose;
@@ -57,3 +57,23 @@ isnt(
     Moose::Object->can('new'),
     'Bar->new is not inherited from NotMoose because it was inlined'
 );
+
+{
+    package Baz;
+    use Moose;
+
+    Baz->meta->make_immutable;
+}
+
+{
+    package Quux;
+    use Moose;
+
+    extends 'Baz';
+
+    ::stderr_is(
+        sub { Quux->meta->make_immutable },
+        q{},
+        'no warning when inheriting from a class that has already made itself immutable'
+    );
+}