Skip Menu |

This queue is for tickets about the Moo CPAN distribution.

Report information
The Basics
Id: 98666
Status: resolved
Priority: 0/
Queue: Moo

People
Owner: Nobody in particular
Requestors: perl [...] toby.ink
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 1.006000
Fixed in: (no value)



Subject: Causing Sub::Defer to undefer early breaks some optimizations in Method::Generate::Construtor
Method::Generate::Constructor will create a constructor which does not call BUILDARGS if it detects that the class' BUILDARGS has been inherited from Moo::Object. This can be subtly broken by calling Sub::Defer::undefer_all() at a strategic moment. (See attached test case.) It can also be caused by other things that result in constructor getting undeferred early, such as an object instantiation. As far as I can tell, the only bullet-proof solution is to always call BUILDARGS. This is a shame, because the current optimization does make a measurable difference. Performance could be regained by creating an XS implementation of Moo::Object::BUILDARGS(), and making that an optional (recommended) dependency for Moo. There may be similar issues around FOREIGNBUILDARGS/BUILDALL/DEMOLISHALL.
Subject: sub-defer-undefer_all-not-charming-not-delightful.t
use strictures; use Test::More; { package Rectangle; use Moo; has height => (is => "ro", required => 1); has width => (is => "ro", required => 1); # Let's assume I actually have a good reason to call # undefer_all here, and cannot just comment it out. # Sub::Defer::undefer_all(); around BUILDARGS => sub { my ($next, $self) = (shift, shift); my $params = $self->$next(@_); $params->{height} //= $params->{width}; $params->{width} //= $params->{height}; return $params; }; } is( Rectangle->new(height => 12)->width, 12 ); is( Rectangle->new(width => 12)->height, 12 ); done_testing();
I'd prefer to solve this more with docs saying "Don't do that". This was discussed somewhat on IRC, and my understanding is that you don't actually need to undefer_all, but that you want to undefer your own packages. Currently, Sub::Defer doesn't provide an API to allow that, so the proposed solution is adding a undefer_package sub undefers all of the subs in a given package. Does this seems like a reasonable solution?
On 2014-10-28T04:44:10Z, haarg wrote: Show quoted text
> Does this seems like a reasonable solution?
Yes.
The next release of Moo will include a Sub::Defer::undefer_package that undefers all subs in a given package.
Fixed in 1.007000