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

monitor methods convert die into crazy #8

Open
japhb opened this issue Oct 29, 2016 · 4 comments
Open

monitor methods convert die into crazy #8

japhb opened this issue Oct 29, 2016 · 4 comments

Comments

@japhb
Copy link

japhb commented Oct 29, 2016

For some reason, ad hoc (die "...") exceptions get swallowed and replaced with a 'Cannot invoke this object (REPR: Null; VMNull)' error; here's a golf:

$ cat A.pm6
use OO::Monitors;
unit monitor A;
method B { say "C"; die "D"; "E" }

$ perl6 -I . -e 'need A; say A.new.B'
C
Cannot invoke this object (REPR: Null; VMNull)
  in block  at .../install/share/perl6/site/sources/B7DF632EBAC65169FAE1AF8BFB774E9775D8BA37 (OO::Monitors) line 33
  in block  at .../install/share/perl6/site/sources/B7DF632EBAC65169FAE1AF8BFB774E9775D8BA37 (OO::Monitors) line 30
  in any enter at gen/moar/m-Metamodel.nqp line 4032
  in block <unit> at -e line 1

Given that the current version of OO::Monitors specifically claims to work around "Cannot invoke this object" errors, something is fishy.

@japhb
Copy link
Author

japhb commented Oct 29, 2016

OK, it may have nothing to do with OO::Monitors per se, just something OO::Monitors happens to do that triggers a different bug. Attacking the golfing problem from another angle, I reached this arrangement:

$ cat K.pm6
use C;
sub L is export { C::D }

$ cat C.pm6
unit module C;

my %h;

INIT %h<c> = -> $x?, $y? { $x + $y };

our sub D {
    say "A";
    say %h<c>();
    say "B";
}

$ perl6 -I . -e "use K; L"
A
Cannot invoke this object (REPR: Null; VMNull)
  in block  at .../Terminal-Print/C.pm6 (C) line 5
  in sub D at .../Terminal-Print/C.pm6 (C) line 9
  in sub L at .../K.pm6 (K) line 2
  in block <unit> at -e line 1

This turns out to be remarkably finicky about the contents of C.pm6. For example, instead of storing the pointy in a hash entry, let's just bind it to a scalar:

$ cat C.pm6
unit module C;

my $h;

INIT $h := -> $x?, $y? { $x + $y };

our sub D {
    say "A";
    say $h();
    say "B";
}

$ perl6 -I . -e "use K; L"
A
Cannot find method 'Any' on object of type List
  in sub D at .../Terminal-Print/C.pm6 (C) line 9
  in sub L at .../Terminal-Print/K.pm6 (K) line 2
  in block <unit> at -e line 1

OK, instead of binding, we'll assign:

$ cat C.pm6
unit module C;

my $h;

INIT $h = -> $x?, $y? { $x + $y };

our sub D {
    say "A";
    say $h();
    say "B";
}

$ perl6 -I . -e "use K; L"
A
Cannot resolve caller infix:<+>(Mu, Mu); none of these signatures match:
    ($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)
    (Date:D $d, Int:D $x)
    (Int:D $x, Date:D $d)
  in block  at .../Terminal-Print/C.pm6 (C) line 5
  in sub D at .../Terminal-Print/C.pm6 (C) line 9
  in sub L at .../Terminal-Print/K.pm6 (K) line 2
  in block <unit> at -e line 1

OK, let's supply sane arguments:

$ cat C.pm6
unit module C;

my $h;

INIT $h = -> $x?, $y? { $x + $y };

our sub D {
    say "A";
    say $h(1,2);
    say "B";
}

$ perl6 -I . -e "use K; L"
A
3
B

Well, that works! But wait, what about if I use a hash again, just with proper arguments this time?

$ cat C.pm6
unit module C;

my %h;

INIT %h<c> = -> $x?, $y? { $x + $y };

our sub D {
    say "A";
    say %h<c>(1,2);
    say "B";
}

$ perl6 -I . -e "use K; L"
A
Cannot invoke this object (REPR: Null; VMNull)
  in block  at .../Terminal-Print/C.pm6 (C) line 5
  in sub D at .../Terminal-Print/C.pm6 (C) line 9
  in sub L at .../Terminal-Print/K.pm6 (K) line 2
  in block <unit> at -e line 1

Boom! What if I get rid of INIT?

$ cat C.pm6
unit module C;

my %h;

%h<c> = -> $x?, $y? { $x + $y };

our sub D {
    say "A";
    say %h<c>(1,2);
    say "B";
}

$ perl6 -I . -e "use K; L"
A
3
B

And now it works again. WAT.

@jonathanstowe
Copy link
Collaborator

Is this a slight variation on https://rt.perl.org/Ticket/Display.html?id=127858 which seems to be that some Code objects don't survive pre-compilation?

@japhb
Copy link
Author

japhb commented Oct 29, 2016

Yeah, I was thinking something similar and then saw your comment, jonathanstowe. Just to confirm, I went back to the second-to-last version above, the one with INIT that fails, and just add no precompilation; at the top:

$ cat C.pm6
no precompilation;

unit module C;

my %h;

INIT %h<c> = -> $x?, $y? { $x + $y };

our sub D {
    say "A";
    say %h<c>(1,2);
    say "B";
}

$ perl6 -I . -e "use K; L"
A
3
B

Sure enough, it works. So there are at least two bugs here: A confirmation of RT #127858 with a few more variants, and that the workaround that OO::Monitors uses doesn't quite work (see the original issue description).

@jnthn
Copy link
Owner

jnthn commented Dec 21, 2016

@japhb So I'm a tad confused. I turned the original issue reported here into what I'm pretty sure is a representative pre-comp test case. The test failed. Then I pulled in the changes from my proposed maybe-fix-exception-stuff branch. That made the test pass. So, that's in the commit I linked.

However, I thought you'd mentioned that the branch did not help? So, I tried your original example:

jnthn@lviv:~/dev/oo-monitors$ cat A.pm6 
use OO::Monitors;
unit monitor A;
method B { say "C"; die "D"; "E" }
jnthn@lviv:~/dev/oo-monitors$ perl6 -I . -e 'need A; say A.new.B'
C
D
  in method B at /home/jnthn/dev/oo-monitors/A.pm6 (A) line 3
  in any call_with_capture at gen/moar/Metamodel.nqp line 3901
  in block  at /home/jnthn/dev/oo-monitors/lib/OO/Monitors.pm6 (OO::Monitors) line 31
  in any enter at gen/moar/Metamodel.nqp line 3999
  in block <unit> at -e line 1

This case seems fixed also (so the test was covering the right thing). Yes, there is a Rakudo bug that also wants looking at, but in all those cases OO::Monitors has been golfed out of the issue.

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

3 participants