katastrophos
katastrophos

Reputation: 531

Compile time issue with MooseX::Aliases, immutable and circular 'use'

I get a compile time error (Moose complains about modifying an immutable instance) running 'perl -c' on a package but code using the package runs error-free. Example Code:

File Pa_1.pm (immutable Moose class using MooseX::Aliases and package Pa_2.pm):

package Pa_1;

use Pa_2;

use Moose;

# uncommenting either this line ...
use MooseX::Aliases;

# ... or this line to make 'perl -c' work
__PACKAGE__->meta->make_immutable;

1;

File Pa_2.pm (just using Pa_1.pm which uses Pa_2.pm):

package Pa_2;

use Pa_1;
1;

File run_pa_1.pl :

#!/usr/bin/env perl

use Pa_1;

my $pa1 = Pa_1->new();
print "Done !\n";

Executing run_pa_1.pl works, but 'perl -c Pa_1.pm' gives

The 'add_method' method cannot be called on an immutable instance at /home/pecho/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/x86_64-linux/Class/MOP/Class/Immutable/Trait.pm line 32.
        Class::MOP::Class::Immutable::Trait::_immutable_cannot_call('add_method') called at /home/pecho/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/x86_64-linux/Class/MOP/Class/Immutable/Trait.pm line 47
        Class::MOP::Class:::around('CODE(0xc10158)', 'Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...', 'DESTROY', 'Moose::Meta::Method::Destructor=HASH(0x14af4f8)') called at /home/pecho/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/x86_64-linux/Class/MOP/Method/Wrapped.pm line 162
        Class::MOP::Method::Wrapped::__ANON__('Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...', 'DESTROY', 'Moose::Meta::Method::Destructor=HASH(0x14af4f8)') called at /home/pecho/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/x86_64-linux/Class/MOP/Method/Wrapped.pm line 91
        Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::SERIAL::1::add_method('Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...', 'DESTROY', 'Moose::Meta::Method::Destructor=HASH(0x14af4f8)') called at /home/pecho/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/x86_64-linux/Class/MOP/Mixin/HasMethods.pm line 181
        Class::MOP::Mixin::HasMethods::_restore_metamethods_from('Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...', 'Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...') called at /home/pecho/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/x86_64-linux/Class/MOP/Class.pm line 405
        Class::MOP::Class::_restore_metaobjects_from('Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...', 'Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...') called at /home/pecho/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/x86_64-linux/Moose/Meta/Class.pm line 728
        Moose::Meta::Class::_restore_metaobjects_from('Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...', 'Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...') called at /home/pecho/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/x86_64-linux/Class/MOP/Class.pm line 65
        Class::MOP::Class::reinitialize('Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...', 'Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...', 'error_class', 'Moose::Error::Default', 'wrapped_method_metaclass', 'Class::MOP::Method::Wrapped', 'instance_metaclass', 'Moose::Meta::Instance', 'method_metaclass', ...) called at /home/pecho/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/x86_64-linux/Moose/Meta/Class.pm line 188            Moose::Meta::Class::reinitialize('Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...', 'Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...', 'attribute_metaclass', 'Moose::Meta::Class::__ANON__::SERIAL::2') called at /home/pecho/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/x86_64-linux/Moose/Util/MetaRole.pm line 99            Moose::Util::MetaRole::_make_new_metaclass('Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...', 'HASH(0x144f868)', 'class') called at /home/pecho/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/x86_64-linux/Moose/Util/MetaRole.pm line 28            Moose::Util::MetaRole::apply_metaroles('for', 'Class::MOP::Class::Immutable::Moose::Meta::Class::__ANON__::S...', 'class_metaroles', 'HASH(0x144f868)', 'role_metaroles', 'HASH(0x144f838)') called at /home/pecho/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/x86_64-linux/Moose/Exporter.pm line 543
        Moose::Exporter::_apply_metaroles('Pa_1', 'ARRAY(0x93c630)', 'CODE(0xddccc8)') called at /home/pecho/perl5/perlbrew/perls/perl-5.16.1/lib/site_perl/5.16.1/x86_64-linux/Moose/Exporter.pm line 460
        Moose::Exporter::__ANON__('MooseX::Aliases') called at Pa_1.pm line 6
        Pa_1::BEGIN() called at Pa_1.pm line 6
        eval {...} called at Pa_1.pm line 6
BEGIN failed--compilation aborted at Pa_1.pm line 6.

I am a little confused because an error is emitted starting perl on Pa_2.pm with compile switch but run time seems to be ok.

Is there a bug in the code, in MooseX::Aliases or is it something internal to Moose ?

Versions used : perl 5.16.1; Moose 2.0604; MooseX::Aliases 0.10;

Upvotes: 0

Views: 324

Answers (2)

ikegami
ikegami

Reputation: 385917

Never execute a module directly. You end up compiling and executing it twice.

Similarly, never compile a module directly. You end up compiling it twice.

perl -c Pa_1.pm

should

perl -c -e'use Pa_1;'

perl -c Pa_1.pm executes the following (ignoring require and import that do nothing):

package Pa_1;
require Pa_2;

package Pa_2;
require Pa_1;

package Pa_1;
require Moose;
import Moose;
require MooseX::Aliases;
import MooseX::Aliases;
__PACKAGE__->meta->make_immutable;
1;

package Pa_2;
1;

package Pa_1;
import Moose;
import MooseX::Aliases;

perl -c -e'use Pa_1; executes the following (ignoring require and import that do nothing):

package Pa_1;
require Pa_2;

package Pa_2;
1;

package Pa_1;
require Moose;
import Moose;
require MooseX::Aliases;
import MooseX::Aliases;
__PACKAGE__->meta->make_immutable;
1;

Notice how you end up doing

import Moose;
import MooseX::Aliases;

after doing

__PACKAGE__->meta->make_immutable;

when you do it wrong?

Upvotes: 1

ErikR
ErikR

Reputation: 52039

Will this ordering in Pa_1.pm work for you?

package Pa_1;

use Moose;
use MooseX::Aliases;

use Pa_2;

__PACKAGE__->meta->make_immutable;

I think it is generally advisable to put all of the Moose modules first.

Upvotes: 0

Related Questions