Ticket #1426 (closed bug: wontfix)

Opened 4 years ago

Last modified 4 years ago

C3 linearizer fails on two plain (P6object) classes

Reported by: Austin_Hastings Owned by:
Priority: normal Milestone:
Component: none Version: 2.0.0
Severity: high Keywords:
Cc: Language:
Patch status: Platform:

Description

This test code:

class Foo::Parent {
	method x() {
		say("x");
	}
}

class Foo::Child {
	method y() {
		say("y");
	}
}

P6metaclass.add_parent(Foo::Child, Foo::Parent);

fails when fed to parrot-nqp:

Could not build C3 linearization: ambiguous hierarchy
current instr.: 'parrot;P6metaclass;add_parent' pc 224 (runtime/parrot/library/P6object.pir:232)
called from Sub '_block11' pc 0 (EVAL_1:6)
called from Sub 'parrot;PCT;HLLCompiler;eval' pc -1 ((unknown file):-1)
called from Sub 'parrot;PCT;HLLCompiler;evalfiles' pc 1303 (src/PCT/HLLCompiler.pir:707)
called from Sub 'parrot;PCT;HLLCompiler;command_line' pc 1489 (src/PCT/HLLCompiler.pir:794)
called from Sub 'parrot;NQP;Compiler;main' pc -1 ((unknown file):-1)

Since the P6object system automatically adds a P6object root class as a parent to created classes, the two classes being merged look like:

P6 -> Child P6 -> Parent

It seems like C3 should be able to work that out.

Change History

Changed 4 years ago by Austin_Hastings

  • status changed from new to closed
  • resolution set to wontfix

I created the C3 linearization page while trying to get my head around how it works, and I believe I understand what is going wrong.

In short, C3 honors the relative order of the parent declarations. This means that saying "Child has parents (P6, Parent)" will prefer P6 in all searches. The ambiguous hierarchy error comes about because Parent has P6 as a parent, meaning it should take precedence, but Child has P6 first in the parents list, meaning that IT should take precedence.

This failure will generally hold whenever one parent, later in the parents list, is a subclass of a parent that appears earlier in the list. C3 is operating as designed.

Unfortunately, as mentioned in my original report, adding a parent to a "trivial" P6object class falls into this category, since the trivial class will have P6object as a parent, and P6object will be a superclass of whatever parent is being added.

As far as I can tell, work-arounds to this include mixing another class into the Child:

class Other;
class Foo::Child is Other;
class Foo::Parent;
P6metaclass.add_parent(Foo::Child, Foo::Parent);

or calling the Class PMC's remove_parent to remove P6object before adding the parent.

Note: See TracTickets for help on using tickets.