[perl #131785] [BUG] - runtime looping.

2017-08-11 Thread Aleks-Daniel Jakimenko-Aleksejev via RT
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  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
>

[perl #131785] [BUG] - runtime looping.

2017-08-10 Thread Brian S. Julin via RT

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  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.



[perl #131785] [BUG] - runtime looping.

2017-07-23 Thread via RT
# New Ticket Created by   
# Please include the string:  [perl #131785]
# in the subject line of all future correspondence about this issue. 
# https://rt.perl.org/Ticket/Display.html?id=131785 >


Greetings!

I have written a module to process some numeric data types and found
that the run time will loop. 

Here is minimal code for the module:

use v6.c;
unit module test1;
our package EXPORT::DEFAULT { # export classes, sub etc.

class Fpa does Numeric {
has UInt $.var is rw = 0;
}

multi infix:<+> ( Fpa:D $left, Fpa:D $right --> Fpa ) is equiv(    
         &infix:«+» ) {
say "here 1!";
return my $newFpa = fpaAdd( $left, $right );
}
multi infix:<+> ( Any:D $left, Fpa:D $right --> Fpa ) is equiv(    
         &infix:«+» ) {
say "here 2!";
return my $newFpa = fpaAdd( $left, $right );
}
multi infix:<+> ( Fpa:D $left, Any:D $right --> Fpa ) is equiv(    
        &infix:«+» ) {
say "here 3!";
return my $newFpa = fpaAdd( $left, $right );
}

our sub fpaAdd ( Fpa:D $left, Fpa:D $right --> Fpa ) {
say "In fpaAdd";
my Int $l = $left.var;
my Int $r = $right.var;
my $z = Fpa.new();
$z.var = $l + $r;
return $z;
}

} # end of package.



Here is some test driver code to call the module (test2.pm6):

use v6c;
use test1;

my Fpa $x = Fpa.new();
say $x.WHAT;
my Fpa $y = Fpa.new();
say $y.WHAT;
$y.var = 5;
$x.var = 1;
say "Object x set to " ~ $x.var ~ '.';
say "Object y set to " ~ $y.var ~ '.';
prompt "Press return and system will go into a loop.";
$x = $x + $y;
say "answer= " ~ $x.var ~ '.'; # This never happens.
exit;

Here is a run of the test2.pm6 code that calls the module:

perl6-m test2.pm6
(Fpa)
(Fpa)
Object x set to 1.
Object y set to 5.
Press return and system will go into a loop.
^C
$ 

Strangely, if the multi are taken out of the module and put in the test
driver, it works as expected.

If the "does Numeric" is removed from the class definition, it does not
resolve a call to a multi infix:<+> despite correctly matching object
types. The error message is:


Cannot resolve caller Numeric(test1::EXPORT::DEFAULT::Fpa: ); none of
these signatures match:
(Mu:U \v: *%_)
  in block  at test2.pm6 line 13

Is this expected behaviour?

Regards,

Andrew N Parker