p5-Mouse
p5-Mouse copied to clipboard
PurePerl object initializers should be compiled in a controlled namespace
In Mouse::Meta::Method::Constructor, the _generate_initialize_object
method generates a coderef by evaluating a string like:
package %s;
sub {
my($meta, $instance, $args, $is_cloning) = @_;
%s;
return $instance;
}
Where the first %s
is the class name that constructor is being compiled in, and the second %s
contains a whole bunch of code dealing with type constraints, defaults, triggers, etc.
That code potentially contains various Perl built-ins like push
. But the class that the constructor is being compiled for might have overridden push
, in which case the compiled object initializer will potentially see the overridden push
instead of CORE::push
.
A quick fix would be something like:
package %s;
sub {
my($meta, $instance, $args, $is_cloning) = @_;
do { package Mouse::Meta::Method::Constructor; %s };
return $instance;
}
This is probably not the only place where this issue occurs, but it's the place that's bitten me.
TLDR:
This warns:
package Foo;
use Mouse;
has bar => ( is => 'ro', trigger => sub {} );
sub push { 1 }
Foo->new( bar => 1 );
This dies:
package Foo;
use Mouse;
use subs 'push';
has bar => ( is => 'ro', trigger => sub {} );
sub push { die; }
Foo->new( bar => 1 );