Re: A plan for fixing _fix_metaclass_compatibility

[email protected] (Stevan Little)
Newsgroups perl.moose
Message-ID <[email protected]>
Dave,

I totally approve of this plan, specific comments below:

On Sep 7, 2008, at 2:01 PM, Dave Rolsky wrote:

> I'm discussing this here cause the plan is kinda long, and wouldn't  
> work well in IRC.
>
> First, the problem ...
>
> With Moose::Util::MetaRole, it's quite easy to end up with a  
> metaclass that is not Moose::Meta::Class. Generaly, it's a subclass  
> of MMC with 1+ roles applied to the subclass. Let's call a subclass  
> that differs from its parent only by the roles it does a "role-only  
> subclass".
>
> Right now, Moose does not handle these sorts of role-only  
> subclasses well when trying to determine if two classes have  
> compatible metaclasses. If two classes each have different role- 
> only subclasses as their metaclass, Moose complains that these  
> metaclasses aren't compatible.
>
> Here's a more concrete example:
>
>   ClassA
>      |
>      |
>   ClassB
>
> ClassB inherits from ClassA. Here's the metaclasses:
>
>              Moose::Meta::Class
>              /                 \
>             /                   \
>         MetaSubA              MetaSubB
>      (for ClassA)             (for ClassB)
>
> The two metaclass subclasses are each role-only subclasses (doing  
> the roles RoleA and RoleB respectively).
>
> When we declare ClassB as a subclass of ClassA, Moose dies. What  
> _should_ happen is that Moose detects that the two metaclasses are  
> role-only, _and_ that they share a common ancestor. Then it can  
> simply make a new metaclass for ClassB which does both RoleA and  
> RoleB, as a subclass of MetaSubA.
>
> Poof, now they're compatible again.

Yes, I think this sounds very sane.

> So that's what I'd like to implement. The algorithm goes like this:
>
> 1. Look for a common parent class between the two metaclasses  
> (often this will end up being Moose::Meta::Class). If there is  
> none, there's an incompatibility. If there are multiple common  
> parents, give up, because I don't want to deal with multiple  
> inheritance ;)
>
> 2. For each class in the chain from a metaclass to the common  
> parent, see if that class is a role-only subclass.
>
> 3a. If all of these subclasses are role-only subclasses _in both  
> chains_, we just need to combine all the roles done in both chains,  
> and make a new subclass for said roles.
>
> 3b. If any of the classes in the chains are _not_ role-only  
> subclasses, we have a real incompatibility, and die just like we do  
> now.
>
> The catch is how to determine if a given metaclass is a role-only  
> subclass, and this is where we get to changing Class::MOP and Moose  
> to support this.
>
> The basic algorithm I've thought of to detect a role-only subclass  
> looks like this. Compare all of this class's attributes and methods  
> to its parent. For any that are specific to the class, see if they  
> come from a role.

This seems like possibly expensive, I wonder if we can't maybe add  
some more meta-data to the metaclass that would maybe track this?  
This is possibly a premature optimization, but I suspect it would  
also mean you wouldn't have to do all the stuff described below too :)

> The last part is what's not really possible with today's CMOP &  
> Moose. We have no good way of knowing the source of an attribute or  
> method, and I want to change that.
>
> My plan is the following:
>
> * Whenever we add a method (add_method or alias_method), we need to  
> accept more than just a name and a sub reference. Instead, we can  
> take a parameter like "source_role" (in Moose) or maybe just  
> "source_package" to make it generate and applicable to CMOP.
>
> * We can do the same thing for attributes. Additionally, I'd like  
> to be able to specify an associated_attribute for methods generated  
> from an attribute. This I want to add just cause we can, and it  
> seems like useful info.
>
> There's one potential stumbling block here. Right now, Method  
> objects are not generated until someone asks for one via an  
> introspection method. To make all this work I think we'll need to  
> generate them as part of add_method, or even just accept such an  
> object in add_method. This means we'll be generating these objects  
> during compile/load time, and paying the cost up front.
>
> So what do people think of this plan?
>
> I'd like to start working on it soon, because the metaclass  
> compatibility thing is biting me in actual code, and working around  
> it is kind of a pain, plus Moose should just get this stuff right  
> anyway.
>
>
> -dave
>
> /*==========================
> VegGuide.Org
> Your guide to all that's veg
> ==========================*/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.