Great analysis! The first issue seems to be already mentioned in RT #126112 (and I vaguely recall one more ticket, but I'm failing to find it now).
This ticket seems to be getting a bit unmanageable, please file smaller tickets for every issue you discover. On 2017-08-10 21:36:34, b...@abrij.org wrote: > > Analysis... you've run into a nest of LTA/bugs. > > 1) First off, this will loop: > > perl6 -e 'class A does Numeric { }; say A.new + A.new' > > The reason it loops is because the default infix:<+> (provided by > Numeric) does this: > > multi sub infix:<+>(\a, \b) { a.Numeric + b.Numeric } > > ...and the default .Numeric, also provided by Numeric, is just { self > } > > This is where the loop comes from. > > The problem would be avoided if the proper infix:<+> candidate were > being > called, but the sanity of Numeric might be improved with something > which > breaks that loop and throws some reasonable exception telling you that > you really need to define a specific candidate... how to implement > that > efficiently might be a challenge. > > 2) A simple explanation would have been that the EXPORT::DEFAULT needs > to contain an &infix:<+> > symbol, and the multis in this package do not provide that symbol. If > you add this > to the EXPORT::DEFAULT package: > > my constant &infix:<+> = &infix:<+>; > > ...then the multis will show up in > &infix:<+>.candidates>>.signature.say > > Whether the presence of those multis should add the Stash key > automatically > when in an EXPORT package is arguably an LTA... probably they see the > Setting's > prototype and do not because a generic package shouldn't. > > 3) But it was not that simple... I know the docs say to, but I'm not > sure > what us gong on with using EXPORT::DEFAULT and "unit module" together. > I know > the intention was to make it work but maybe NYI? The first > questionable thing > to notice is that after a "use test1" an EXPORT::DEFAULT Stash is in > your namespace: > > $ PERL6LIB="/tmp/" perl6 -e 'use v6.c; use test1; > EXPORT::DEFAULT::.keys.say;' > (Fpa &fpaAdd) > > ... I don't think this is supposed to happen; you should get > test1::EXPORT::DEFAULT > instead. That Stash is empty: > > $ PERL6LIB="/tmp/" perl6 -e 'use v6.c; use test1; > test1::EXPORT::DEFAULT::.keys.say;' > > Could not find symbol '&DEFAULT' > in block <unit> at -e line 1 > > But, despite this, the Fpa class does seem to be available and the > multis seem to be > added with this formulation, albeit with ugly test1::EXPORT::DEFAULT > prefixes due to > the location of the class definition. > > Now I'll assume you are using EXPORT::DEFAULT rather than just marking > things as > "is export" for a good reason, so we'll humor that and see whether we > can > find a formulation that works... because it should be possible to do > things > with this form if you really want to. > > 4) I found that even with the candidates in your module available, > Numeric's infix:<+> > was still being called. However, if you jam any additional random > multi candidate into > infix:<+> in your mainline, this seems to jog things into finding the > candidates: > > ...but without that extra candidate it still ends up in > Numeric::infix<+>(\a, \b). > > $ PERL6LIB="/tmp/" perl6 --ll-exception -e 'use v6.c; use test1; > EXPORT::DEFAULT::.keys.say; my Fpa $x = Fpa.new(); my Fpa $y = > Fpa.new(); $y.var = 5; $x.var = 1; say $x.perl, $y.perl; say > &infix:<+>.candidates>>.signature; class foobar { }; multi sub > infix:<+> (foobar $, foobar $) { }; say ($x + $y).perl' > (Fpa &fpaAdd) > test1::EXPORT::DEFAULT::Fpa.new(var => > 1)test1::EXPORT::DEFAULT::Fpa.new(var => 5) > (($x = 0) (\a, \b) (Real \a, Real \b) (Int:D \a, Int:D \b --> Int:D) > (int $a, int $b --> int) (Num:D \a, Num:D \b) (num $a, num $b --> num) > (Range:D \a, Real:D \b) (Real:D \a, Range:D \b) (Rational \a, Rational > \b) (Rational \a, Int \b) (Int \a, Rational \b) (Complex:D \a, > Complex:D \b --> Complex:D) (Complex:D \a, Real \b --> Complex:D) > (Real \a, Complex:D \b --> Complex:D) (Instant:D $a, Real:D $b) > (Real:D $a, Instant:D $b) (Instant:D $a, Duration:D $b) (Duration:D > $a, Instant:D $b) (Duration:D $a, Real $b) (Real $a, Duration:D $b) > (Duration:D $a, Duration:D $b) (DateTime:D \a, Duration:D \b) > (Duration:D \a, DateTime:D \b) (Date:D $d, Int:D $x) (Int:D $x, Date:D > $d) (test1::EXPORT::DEFAULT::Fpa:D $left, > test1::EXPORT::DEFAULT::Fpa:D $right --> test1::EXPORT::DEFAULT::Fpa) > (Any:D $left, test1::EXPORT::DEFAULT::Fpa:D $right --> > test1::EXPORT::DEFAULT::Fpa) (test1::EXPORT::DEFAULT::Fpa:D $left, > Any:D $right --> test1::EXPORT::DEFAULT::Fpa) (foobar, foobar)) > here 1! > In fpaAdd > test1::EXPORT::DEFAULT::Fpa.new(var => 6) > > ...this, however, might be a consequence of the value of the > 'infix:<+>' constant > I installed earlier to fix #2 above... may somehow have gotten glued > to a too-specific > compiler construct (fold/spesh/opt) > > Do note that the (Any:D $, Fpa:D $) and (Fpa:D $, Any:D $) will fail > as written > since they don't convert the non-Fpa parameter or do anything special, > but probably > this was expected and you just wanted to see it reaching the "say." > > I'd dig deeper but I must rest now.