Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should Perl 6 be able to untangle the inclusion of the same role from different sources? #6030

Closed
p6rt opened this issue Jan 24, 2017 · 5 comments

Comments

@p6rt
Copy link

p6rt commented Jan 24, 2017

Migrated from rt.perl.org#130634 (status was 'open')

Searchable as RT130634$

@p6rt
Copy link
Author

p6rt commented Jan 24, 2017

From @briandfoy

I posted this to Stackoverflow without anyone pointing out the error
of my ways, so I think this is probably a bug.

  http://stackoverflow.com/q/41791602/2766176

Imagine a series of complex grammars represented as roles, although
this simple example is enough to show the conflict​:

  role Alpha {
  token alpha { :i <[A..Z]> }
  }

  role Digit {
  token digit { <[0..9]> }
  }

  role Either
  does Alpha
  does Digit {
  token either { <alpha> | <digit> }
  }

  grammar Thingy
  does Either
  does Alpha
  {
  token TOP { <alpha> <either>* }
  }

  my $match = Thingy.parse( '1a3' );
  dd $match;

This doesn't work because Perl 6 doesn't untangle the relationships to
figure out that the conflict is actually the same thing from the same
source​:

  Method 'alpha' must be resolved by class Thingy because it exists
  in multiple roles

But, reading [S14](https://design.perl6.org/S14.html), I see​:

  A role may not inherit from a class, but may be composed of other
  roles. However, this "crony" composition is not evaluated until
  class composition time. This means that if two roles bring in the
  same crony, there's no conflict--it's just as if the class pulled
  in the crony role itself and the respective roles didn't. A role
  may never conflict with itself regardless of its method of
  incorporation.

I read that to mean that the roles are applied as late as possible, so
the class `Thingy` would be able to disentangle that `Alpha` is
included in two different parts. I figured this would work something
like creating a list of all of the roles that would make up the final
class, then applying that list only to the final class. That way,
something like `Either` would mix-in only the things it defined and
would rely on the later composition to bring in `Alpha`.

I ran across this when I was trying to implement grammars for various
(IETF) RFCs. Many of them reference the grammars from other RFCs,
which makes it impossible for Perl 6 to resolve inheritance by C3. So,
I figured that roles would disconnect the relationships. Apparently it
doesn't.

@p6rt
Copy link
Author

p6rt commented Jan 25, 2017

From @raiph

Golf'd to​:

role A { method m {} }
role B does A {}
class C does A does B {}

Method 'm' must be resolved by class C because it exists in multiple roles
(A, B)

Note that the same issue leads also to​:

role A { has $a }
role B does A {}
class C does A does B {}

Attribute '$!a' conflicts in role composition

A number of devs discussed this on #perl6 with the useful part starting
here​:

https://irclog.perlgeek.de/perl6/2017-01-24#i_13982402

and ending with jnthn's thoughts.

--
raiph

@p6rt
Copy link
Author

p6rt commented Jan 25, 2017

The RT System itself - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

p6rt commented Aug 29, 2017

From @skids

On Tue, 24 Jan 2017 17​:11​:13 -0800, raiph wrote​:

Golf'd to​:

role A { method m {} }
role B does A {}
class C does A does B {}

Method 'm' must be resolved by class C because it exists in multiple roles
(A, B)

Note that the same issue leads also to​:

role A { has $a }
role B does A {}
class C does A does B {}

Attribute '$!a' conflicts in role composition

A number of devs discussed this on #perl6 with the useful part starting
here​:

https://irclog.perlgeek.de/perl6/2017-01-24#i_13982402

and ending with jnthn's thoughts.

I have a fix for this, see​:

https://gist.github.com/skids/18fa6fb1de776400abd43b6e82e9fcc2

I just have to resist Warnock's Dilemna and pester people just the riht amount
until someone has the time to review it so it can be improved a bit.

Also, RT#​124749 can be combined with this.

Locally, using the above linked branch​:

$ perl6 -e 'role A { method m { 42.say } }; role B does A {}; class C does A does B {}; C.new.m()'
42
$ perl6 -e 'role A { has $.a = 42 }; role B does A {} ; class C does A does B {}; C.new.a.say'
42

@usev6
Copy link

usev6 commented Oct 7, 2023

It looks like this problem has been solved in the meantime.

The code from original bug report doesn't error out anymore.

$ ./rakudo-m -e 'role Alpha { token alpha { :i <[A..Z]> } }; role Digit { token digit { <[0..9]> } }; role Either does Alpha does Digit { token either { <alpha> | <digit> } }; grammar Thingy does Either does Alpha { token TOP { <alpha> <either>* } }; my $match = Thingy.parse("1a3"); dd $match'
Any $match = Any

The result looks reasonable, because the parsed string starts with a digit. Parsing "b1a3" matches more (please note, that I use say instead of dd to get a nicer output for this issue):

$ ./rakudo-m -e 'role Alpha { token alpha { :i <[A..Z]> } }; role Digit { token digit { <[0..9]> } }; role Either does Alpha does Digit { token either { <alpha> | <digit> } }; grammar Thingy does Either does Alpha { token TOP { <alpha> <either>* } }; my $match = Thingy.parse("b1a3"); say $match'
「b1a3」
 alpha => 「b」
 either => 「1」
  digit => 「1」
 either => 「a」
  alpha => 「a」
 either => 「3」
  digit => 「3」

The golfed code also works as expected:

$ ./rakudo-m -e 'role A { method m { 42.say } }; role B does A {}; class C does A does B {}; C.new.m()'
42
$ ./rakudo-m -e 'role A { has $.a = 42 }; role B does A {}; class C does A does B {}; C.new.a.say'
42

For the record a working link for the discussion mentioned above: https://colabti.org/irclogger/irclogger_log/perl6?date=2017-01-24#l795

If I understand correctly this has been fixed by @vrurg: https://blogs.perl.org/users/vadim_belman/2019/12/post.html (search for "diamond consumption"). The OP also linked to this blog post in the Stackoverflow post.

If I'm not mistaken the bug reported in this issue is covered by the following test in roast: https://github.com/Raku/roast/blob/35456a1a68/S14-roles/composition.t#L77-L83. So I'm going to close the issue without adding another test. (Please reopen if I'm wrong and we need more tests.)

@usev6 usev6 closed this as completed Oct 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants