On Mon, 07 Aug 2017 08:25:10 -0700, c...@zoffix.com wrote: > On Thu, 29 Jun 2017 03:46:02 -0700, c...@zoffix.com wrote: > > Mu provides iterator method, but when you mix in a role that wants it > > implemented, it doesn't find it: > > > > m: role Meow { method iterator {…} }; class Bar does Meow {} > > camelia rakudo-moar 2a8d1e: OUTPUT: «5===SORRY!5=== Error while > > compiling <tmp>â¤Method 'iterator' must be implemented by Bar > > because > > it is required by roles: Meow.â¤at <tmp>:1â¤Â» > > > > Yet it all works fine if you are also doing `is SomethingUnrelated`: > > > > m: class Foo { method x {} }; role Meow { method iterator {…} }; > > class > > Bar is Foo does Meow {} > > camelia rakudo-moar 2a8d1e: ( no output ) > > > Another example turned up; fails to notice the method is provided by > `handles`: > > class HTTP::Header does Associative does Iterable { > subset StrOrArrayOfStr where Str | ( Array & {.all ~~ Str} ); > > has %!fields of StrOrArrayOfStr > handles <AT-KEY EXISTS-KEY DELETE-KEY push > iterator list kv keys values>; > > method Str { #`[not shown, for brevity] } > } > > This is from https://github.com/perl6/doc/issues/1438
I've traced this as far back as RoleToClassApplier.has_method not getting anything in .^mro except itself... unless there is an "is", in which case it gets the inherited class. It will then get Any/Mu thereby. Unless that "is" was an "is Mu" in which case it only gets Mu: # This fails... .elems is from Any and compute_mro recurses # into the type in the "is". perl6 -e 'role Meow { method elems {...} }; class Boo { }; class Bar is Mu does Meow { }; Bar.^mro.say' It looks like with a not-yet-composed class C3MRI.compute_mro will not find Any/Mu... it is not the case that comput_mro was called even earlier than this and cached an incomplete $!mro. There must be a fixup to prevent this situation because: $ perl6 -e 'role Meow { method split {...} }; class Boo { }; class Bar does Meow { method split { 42 } }; Bar.^mro.say' ((Bar) (Any) (Mu)) ...the code in C3MRO if left to its own devices would have left Bar with only itself in .^mro in this situation. Tracing it back up, if you look several lines under the call to RoleToClassApplier.apply, you'll see the code that adds .get_default_parent_type to the mro. I'm too tired to try at the moment, but either this needs to be done earlier, or we need to emulate it in RoleToClassApplier.