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.

Reply via email to