So, after a discussion with mst in #moose, he pointed out that
initializing a non-Moose class with a Moose metaclass is a bug, and we
really shouldn't be doing it. This occurs quite a bit in code within
CMOP and Moose, which does things like:

  for my $class ($self->linearized_isa) {
      my $meta = $self->initialize($class);
      ...
  }

and similarly with $self->superclasses, etc. When called on a Moose
class, this will initialize any non-Moose ancestors with a metaclass of
Moose::Meta::Class, which isn't really correct.

I looked into this, and it seems like the only way to accomplish this
safely is to not cache metaclasses which aren't explicitly initialized.
I've implemented this on the topic/nonmoose_gets_cmop_meta branches of
CMOP and Moose (the name is from an earlier attempt which used a
different strategy). It seems to work properly, and fixes the issues
that I've been able to find, but I was wondering if people think this is
a sane thing to want to do, or if this is going to cause other issues
down the road.

Another possible solution to this problem would be to force all classes
which get incidentally initialized like this to have CMOP metaclasses,
but this tends to break in complicated inheritance situations - for
instance, Moose::init_meta won't reinitialize a class with a CMOP
metaclass to have a Moose metaclass, it just throws an error (probably
since upgrading the metaclass in a safe way that preserves things like
existing attributes and such would be a pain). Also, in some situations,
the temporary metaclass needs to be a Moose::Meta::Class -
_fix_metaclass_incompatibility for instance doesn't exist in CMOP, so in
a Moose - non-Moose - Moose inheritance setup, the non-Moose class needs
to get a Moose metaclass to run _fix_metaclass_incompatibility on to see
if it is going to need fixing (this isn't a big deal, since metaclass
compatibility means that it needs to have a Moose metaclass anyway, but
still something to watch out for).

So... any thoughts?

-doy

Reply via email to