GNU bug report logs - #42345
3.0.4 says "wrong num' of arg's to 1" vs 2.2.4: "wrong num' of arg's to baz"

Previous Next

Package: guile;

Reported by: Matt Wette <matt.wette <at> gmail.com>

Date: Mon, 13 Jul 2020 16:42:01 UTC

Severity: normal

Merged with 42757

Found in version 3.0.4

To reply to this bug, email your comments to 42345 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-guile <at> gnu.org:
bug#42345; Package guile. (Mon, 13 Jul 2020 16:42:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Matt Wette <matt.wette <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-guile <at> gnu.org. (Mon, 13 Jul 2020 16:42:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Matt Wette <matt.wette <at> gmail.com>
To: bug-guile <at> gnu.org
Subject: 3.0.4 says "wrong num' of arg's to 1" vs 2.2.4: "wrong num' of arg's
 to baz"
Date: Mon, 13 Jul 2020 09:41:06 -0700
In Guile 3.0.4, the program below results in the error:

/home/mwette/zz.scm:5:2: In procedure bar:
Wrong number of arguments to 1


In Guile 2.2.4, the same program results in the error:

;;; /home/mwette/zz.scm:11:14: warning: wrong number of arguments to `bar'
;;; compiled 
/home/mwette/.cache/guile/ccache/2.2-LE-8-3.A/home/mwette/zz.scm.go


However, once compiled, Guile 3.0.4, will repeat the same error message,
while Guile 2.2.4, will not report any error.

I consider reporting "1" as the name of a procedure a bug.

Here is the program:
(define (foo)

  (define (bar a b)
    (+ a b))

  (define (baz)
    (let* ((a 1)
       (b 2)
       (r (bar a b a)))
      r))

  (baz))

(foo)





Merged 42345 42757. Request was from Taylan Kammer <taylan.kammer <at> gmail.com> to control <at> debbugs.gnu.org. (Sun, 23 May 2021 19:59:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-guile <at> gnu.org:
bug#42345; Package guile. (Sun, 23 May 2021 22:12:02 GMT) Full text and rfc822 format available.

Message #10 received at 42345 <at> debbugs.gnu.org (full text, mbox):

From: Taylan Kammer <taylan.kammer <at> gmail.com>
To: 42345 <at> debbugs.gnu.org
Cc: Andy Wingo <wingo <at> pobox.com>, Christopher Lam <christopher.lck <at> gmail.com>,
 Matt Wette <matt.wette <at> gmail.com>
Subject: "Wrong number of arguments to 1"
Date: Mon, 24 May 2021 00:11:10 +0200
Note: merged with https://bugs.gnu.org/42757 as it's the same bug.

Andy is in CC since we almost certainly need his input. :-)


I've been working on this since a few days (had to learn much about the VM)
and here's an explanation of what's going on.


Firstly here's a minimal procedure that exhibits the bug:

  (define (test x)
    (define (inner-proc a) #f)
    (inner-proc 0 x))


Calling this procedure will always result in the error message:

  Wrong number of arguments to 0


Because the first argument to inner-proc is 0.  Were the first argument x,
then the argument we pass to 'test' would appear in the error message.

That's our bug at a high level: the first argument to inner-proc being
reported as the procedure that raised the error.


The disassembly is quite slim:


Disassembly of #<procedure test (x)> at #x559c98764348:

   0    (instrument-entry 82)
   2    (assert-nargs-ee/locals 2 0)    ;; 2 slots (1 arg)
   3    (make-immediate 1 2)            ;; 0
   4    (handle-interrupts)
   5    (tail-call-label 2)             ;; inner-proc at #x559c98764364

----------------------------------------
Disassembly of inner-proc at #x559c98764364:

   0    (instrument-entry 81)
   2    (assert-nargs-ee/locals 1 0)    ;; 1 slot (0 args)
   3    (make-immediate 0 4)            ;; #f
   4    (handle-interrupts)             
   5    (return-values)                 


Here's some explanations for those who aren't savvy with the VM, starting
from the top.  (The instructions, like assert-nargs-ee/locals, are defined
in libguile/vm-engine.c.)

Ignore the instrument-entry and handle-interrupts instructions.

- (assert-nargs-ee/locals 2 0) checks the number of arguments, ensuring
  that there's a total of 2 slots on the stack. [1]

- (make-immediate 1 2) puts the Scheme number 0 in slot 0. [2]

- (tail-call-label 2) jumps to the beginning of inner-proc. [3]

- (assert-nargs-ee/locals 1 0) checks the number of arguments, ensuring
  that there's a total of 1 slot on the stack. [4]

That's where the error is raised, by calling error_wrong_num_args from
libguile/intrinsics.c, because there's 2 slots on the stack, not 1.
Error_wrong_num_args tries to get the currently executed procedure from
slot 0, and finds the number 0 there, wrongly using that instead.

[1] Slot 0 is usually filled with the procedure being executed itself,
    before it's called, so the number of slots is usually the number of
    arguments plus one.

[2] Slot references in the VM are referenced backwards from N-1 to 0,
    where N is the number of slots.  In our case, as we have 2 slots,
    the number 1 refers to slot 0.  The reason has to do with the Guile
    stack growing downwards.  The constant 0 is represented by 2 because
    of its type tag as an "immediate" int, see scm.h for details.

[3] The 2 represents the relative position of the first instruction of
    inner-proc, in 4-byte units.  It's pretty close, as it's compiled
    right aside our top-level procedure 'test'.  Since we're currently
    on instruction 5 of 'test', and instructions are 4 bytes long, and
    'test' begins at 0x559c98764348, this means we're jumping to:

      0x559c98764348 + 5*4 + 2*4 = 0x559c98764364

    Which happens to be the address of inner-proc, see? :-)

[4] I don't know why only one slot even though it has one argument; it
    should be two slots.  Maybe an optimization, as the compiler decides
    that the procedure doesn't ever need a reference to itself?


To summarize: for some reason the compiler decides to *not* use an extra
slot for the currently-executed procedure when calling inner-proc, which
leads to the first argument to inner-proc (in this case 0) being used as
the "procedure being executed" during error reporting.

Perhaps that optimization (assuming it is one and not simply a bug in
the compiler) should be disabled, or maybe the code shouldn't even
compile since it can be statically proven that a procedure is being
called with the wrong number of arguments.  This is where I defer to
the Guile compiler experts.

-- 
Taylan




This bug report was last modified 2 years and 344 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.