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

Missing signature with multi sub on REPL #3925

Closed
matiaslina opened this issue Sep 19, 2020 · 3 comments
Closed

Missing signature with multi sub on REPL #3925

matiaslina opened this issue Sep 19, 2020 · 3 comments

Comments

@matiaslina
Copy link

The Problem

Given the following snippet:

multi sub ackermann(0, Int $n) {
    $n + 1;
}

multi sub ackermann(Int $m, 0) {
    ackermann $m - 1, 1;
}

multi sub ackermann(Int $m, Int $n) {
    ackermann $m - 1, ackermann $m, $n - 1;
}

say ackermann 3, 4;

The last definition of ackermann seems to not being defined. On the repl the output of the last line is:

> say ackermann 3, 4;
Cannot resolve caller ackermann(Int:D, Int:D); none of these signatures match:
    (0, Int $n)
    (Int $m, 0)
  in sub ackermann at <unknown file> line 3
  in sub ackermann at <unknown file> line 3
  in sub ackermann at <unknown file> line 3
  in sub ackermann at <unknown file> line 3
  in sub ackermann at <unknown file> line 3
  in block <unit> at <unknown file> line 2

BUT saving that snippet on a file and running it gives no error:

% cat /tmp/raku-repl-bug.raku                                                  
multi sub ackermann(0, Int $n) {
    $n + 1;
}

multi sub ackermann(Int $m, 0) {
    ackermann $m - 1, 1;
}

multi sub ackermann(Int $m, Int $n) {
    ackermann $m - 1, ackermann $m, $n - 1;
}

say ackermann 3, 4;
[~]
% raku /tmp/raku-repl-bug.raku 
125

Expected Behavior

Print 125 in the REPL

Actual Behavior

Cannot resolve caller ackermann(Int:D, Int:D) error.

Steps to Reproduce

  1. Run the raku repl.
  2. Paste the snippet.

Environment

  • Operating system:
% uname -a
Linux archlinux 5.8.3-arch1-1 #1 SMP PREEMPT Fri, 21 Aug 2020 16:54:16 +0000 x86_64 GNU/Linux
  • Compiler version (perl6 -v or raku -v):
% raku -v                                                                      
This is Rakudo version 2020.07 built on MoarVM version 2020.07
implementing Raku 6.d.
@lizmat
Copy link
Contributor

lizmat commented Nov 21, 2020

Thank you for your report!

I'm afraid this is a deficiency of the REPL that will be hard to fix. When you execute your example, the third candidate does appear to exist:

> dd $_ for &ackermann.candidates
Sub ackermann = multi sub ackermann (0, Int $n) { #`(Sub|140652663481776) ... }
Sub ackermann = multi sub ackermann (Int $m, 0) { #`(Sub|140652958975392) ... }
Sub ackermann = multi sub ackermann (Int $m, Int $n) { #`(Sub|140652958975536) ... }

If one reverses the order in which the subs are defined, calling the ackermann function actually hangs:

> multi sub ackermann(Int $m, Int $n) { ackermann $m - 1, ackermann $m, $n - 1; }
&ackermann
> multi sub ackermann(Int $m, 0) { ackermann $m - 1, 1; }
&ackermann
> multi sub ackermann(0, Int $n) { $n + 1 }
&ackermann
> say ackermann 3, 4;
^C

If you define all of the candidates in a single line, and then call the ackermann function, it works as expected:

> multi sub ackermann(0, Int $n) { $n + 1 }; multi sub ackermann(Int $m, 0) { ackermann $m - 1, 1; }; multi sub ackermann(Int $m, Int $n) { ackermann $m - 1, ackermann $m, $n - 1; }
&ackermann
> say ackermann 3, 4
125

The problem is caused by a deficiency in how the REPL handles multiple lines of code: each line is its own compilation unit, and some tricks are being done to pass on the results of earlier lines. But this is known to have some issues that some people run into, like you did.

In this case, I think the problem is that even though the last ackermann function definition knows about all 3 candidates, the second one only "knows" about itself and the ones before. So that is why the error is stating it cannot find the Int:D, Int:D candidate:

Cannot resolve caller ackermann(Int:D, Int:D); none of these signatures match:
    (0, Int $n)
    (Int $m, 0)

while "clearly" there is such a candidate after the third candidate got defined.

I'm afraid this will be pretty hard to fix generally, so I'm going to close this issue as a "won't fix". Please re-open if you disagree.

@lizmat lizmat closed this as completed Nov 21, 2020
@Altai-man
Copy link
Member

@lizmat I thought "torture developers" was the motto all the time, no? The REPL indeed has issues, and that's the reason for its re-design/re-write when anyone is brave and skilled enough to do that.
I don't remember "very hard to fix" being a reason for WONTFIX. "It's simply nearly impossible" - yes. Is this latter or former?

@lizmat lizmat reopened this Nov 22, 2020
lizmat added a commit that referenced this issue Nov 22, 2020
Basically, any line that does *not* create any direct output to
STDOUT, becomes part of the code that will be executed whenever
the next line is input.  This is a behaviour similar to what is
done when a line is deemed incomplete.  The only difference is,
is that this new behaviour will not be visible because of a prompt
change.

This fixes a number of issues with information being lost between
lines, makes a TODO pass in t/02-rakudo/repl.t and is basically a
fix for issues #2284 and #3925.  Matias Linares++ Altai-man++ for
keeping me tortured :-)

Please be aware that this potentially opens a whole new nest of
REPL bugs.  We'll cross that bridge when we get there.
@lizmat
Copy link
Contributor

lizmat commented Nov 22, 2020

Fixed with 7c0a81f501 :-)

@lizmat lizmat closed this as completed Nov 22, 2020
timo pushed a commit to timo/rakudo that referenced this issue Dec 2, 2020
Basically, any line that does *not* create any direct output to
STDOUT, becomes part of the code that will be executed whenever
the next line is input.  This is a behaviour similar to what is
done when a line is deemed incomplete.  The only difference is,
is that this new behaviour will not be visible because of a prompt
change.

This fixes a number of issues with information being lost between
lines, makes a TODO pass in t/02-rakudo/repl.t and is basically a
fix for issues rakudo#2284 and rakudo#3925.  Matias Linares++ Altai-man++ for
keeping me tortured :-)

Please be aware that this potentially opens a whole new nest of
REPL bugs.  We'll cross that bridge when we get there.
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