Search code examples
perloopmoose

Method name conflicts in Moose roles


What I would like to achieve is to create a Moose class that imports several roles. This is something I've been doing for years with no issues, though I am currently stuck on why the simple example below will generate method name conflicts.

package logrole;

use Moose::Role;
use POSIX;
use namespace::autoclean;

package otherrole;

use Moose::Role;
use File::Temp;
use namespace::autoclean;

package myclass;

use Moose;
use namespace::autoclean;
with 'logrole', 'otherrole'; 

package main;

use strict;
use warnings;
use myclass;

Running this gives:

Due to method name conflicts in roles 'logrole' and 'otherrole', the methods 'SEEK_CUR', 'SEEK_END', and 'SEEK_SET' must be implemented or excluded by 'myclass' at /home/user/perl5/perlbrew/perls/perl-5.22.1/lib/site_perl/5.22.1/x86_64-linux/Moose/Exporter.pm line 419
Moose::with('logrole', 'otherrole') called at roles.pl line 29

According to the docs you can exclude method names when consuming a role like so:

package logrole;

use Moose::Role;
use POSIX;
use namespace::autoclean;

package otherrole;

use Moose::Role;
use File::Temp;
use namespace::autoclean;

package myclass;

use Moose;
use namespace::autoclean;
with 'logrole', 'otherrole' => { -excludes => ["SEEK_CUR", "SEEK_END", "SEEK_SET" ] };

package main;

use strict;
use warnings;
use myclass;

This solves the name conflicts, but the problem with this solution is that trying to import POSIX in otherrole generates hundreds of name conflicts, so the fix of excluding all these in the module myclass seems very messy.

How can I import (or write) these roles to avoid the method name conflicts?


Solution

  • namespace::autoclean doesn't remove methods, and it trusts Class::MOP::Class's get_method_list to return them. Confusingly, it returns all the constants from the POSIX module.

    If you switch namespace::autoclean to namespace::clean, the problems are gone.