Allow superclass to provide conflicting methods (RT#91054)
[gitmo/Role-Tiny.git] / lib / Role / Tiny.pm
index a628cc7..a68e379 100644 (file)
@@ -198,7 +198,9 @@ sub apply_roles_to_package {
   return $me->apply_role_to_package($to, $roles[0]) if @roles == 1;
 
   my %conflicts = %{$me->_composite_info_for(@roles)->{conflicts}};
-  delete $conflicts{$_} for keys %{ $me->_concrete_methods_of($to) };
+  my @have = grep $to->can($_), keys %conflicts;
+  delete @conflicts{@have};
+
   if (keys %conflicts) {
     my $fail = 
       join "\n",
@@ -210,6 +212,15 @@ sub apply_roles_to_package {
     die $fail;
   }
 
+  # conflicting methods are supposed to be treated as required by the
+  # composed role. we don't have an actual composed role, but because
+  # we know the target class already provides them, we can instead
+  # pretend that the roles don't do for the duration of application.
+  my @role_methods = map $me->_concrete_methods_of($_), @roles;
+  # separate loops, since local ..., delete ... for ...; creates a scope
+  local @{$_}{@have} for @role_methods;
+  delete @{$_}{@have} for @role_methods;
+
   # the if guard here is essential since otherwise we accidentally create
   # a $INFO for something that isn't a Role::Tiny (or Moo::Role) because
   # autovivification hates us and wants us to die()