Skip to content

Commit

Permalink
Make it verify (again) the stubed methods from roles, not implemented…
Browse files Browse the repository at this point in the history
… before, after the attributes composition (to check if it was implemented by a 'handles' from an attribute). Related to #2386. Needs test
  • Loading branch information
FCO committed Oct 18, 2018
1 parent b50aa51 commit fd5d5bd
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
27 changes: 26 additions & 1 deletion src/Perl6/Metamodel/ClassHOW.nqp
Expand Up @@ -68,11 +68,26 @@ class Perl6::Metamodel::ClassHOW
@!fallbacks[+@!fallbacks] := %desc;
}

sub has_method($target, $name) {
for $target.HOW.mro($target) {
my %mt := nqp::hllize($_.HOW.method_table($_));
if nqp::existskey(%mt, $name) {
return 1;
}
%mt := nqp::hllize($_.HOW.submethod_table($_));
if nqp::existskey(%mt, $name) {
return 1;
}
}
return 0;
}

method compose($obj, :$compiler_services) {
# Instantiate all of the roles we have (need to do this since
# all roles are generic on ::?CLASS) and pass them to the
# composer.
my @roles_to_compose := self.roles_to_compose($obj);
my @stubs;
if @roles_to_compose {
my @ins_roles;
while @roles_to_compose {
Expand All @@ -84,7 +99,7 @@ class Perl6::Metamodel::ClassHOW
nqp::push(@!concretizations, [$r, $ins]);
}
self.compute_mro($obj); # to the best of our knowledge, because the role applier wants it.
RoleToClassApplier.apply($obj, @ins_roles);
@stubs := RoleToClassApplier.apply($obj, @ins_roles);

# Add them to the typecheck list, and pull in their
# own type check lists also.
Expand Down Expand Up @@ -116,6 +131,16 @@ class Perl6::Metamodel::ClassHOW
# Compose attributes.
self.compose_attributes($obj, :$compiler_services);

# Test the remaining stubs
for @stubs -> %data {
if !has_method(%data<target>, %data<name>) {
nqp::die("Method '" ~ %data<name> ~ "' must be implemented by " ~
%data<target>.HOW.name(%data<target>) ~
" because it is required by roles: " ~
nqp::join(", ", %data<needed>) ~ ".");
}
}

# See if we have a Bool method other than the one in the top type.
# If not, all it does is check if we have the type object.
unless self.get_boolification_mode($obj) != 0 {
Expand Down
9 changes: 4 additions & 5 deletions src/Perl6/Metamodel/RoleToClassApplier.nqp
Expand Up @@ -99,6 +99,8 @@ my class RoleToClassApplier {
}
}

my @stubs;

# Compose in any methods.
sub compose_method_table(%methods) {
for %methods {
Expand All @@ -116,10 +118,7 @@ my class RoleToClassApplier {
}
}
}
nqp::die("Method '$name' must be implemented by " ~
$target.HOW.name($target) ~
" because it is required by roles: " ~
nqp::join(", ", @needed) ~ ".");
nqp::push(@stubs, nqp::hash('name', $name, 'needed', @needed, 'target', $target));
}
}
elsif !has_method($target, $name, 1) {
Expand Down Expand Up @@ -211,6 +210,6 @@ my class RoleToClassApplier {
}
}

1;
@stubs;
}
}

0 comments on commit fd5d5bd

Please sign in to comment.