]> git.eshelyaron.com Git - emacs.git/commitdiff
Warn about arity errors in inlining calls (bug#12299)
authorMattias Engdegård <mattiase@acm.org>
Thu, 22 Jul 2021 13:00:17 +0000 (15:00 +0200)
committerMattias Engdegård <mattiase@acm.org>
Fri, 23 Jul 2021 13:19:01 +0000 (15:19 +0200)
Wrong number of arguments in inlining function calls (to `defsubst` or
explicitly using `inline`) did not result in warnings, or in very
cryptic ones.

* lisp/emacs-lisp/byte-opt.el (byte-compile-inline-expand): Add calls
to `byte-compile--check-arity-bytecode`.
* lisp/emacs-lisp/bytecomp.el (byte-compile-emit-callargs-warn)
(byte-compile--check-arity-bytecode): New functions.
(byte-compile-callargs-warn): Use factored-out function.
* test/lisp/emacs-lisp/bytecomp-resources/warn-callargs-defsubst.el:
* test/lisp/emacs-lisp/bytecomp-tests.el ("warn-callargs-defsubst.el"):
New test case.

lisp/emacs-lisp/byte-opt.el
lisp/emacs-lisp/bytecomp.el
test/lisp/emacs-lisp/bytecomp-resources/warn-callargs-defsubst.el [new file with mode: 0644]
test/lisp/emacs-lisp/bytecomp-tests.el

index 341643c7d16a6bc9863715841ba44f0f9d785d9c..ad9f827171a1c1c1494bc3495f56023b95bb7000 100644 (file)
@@ -274,6 +274,7 @@ Earlier variables shadow later ones with the same name.")
       ((pred byte-code-function-p)
        ;; (message "Inlining byte-code for %S!" name)
        ;; The byte-code will be really inlined in byte-compile-unfold-bcf.
+       (byte-compile--check-arity-bytecode form fn)
        `(,fn ,@(cdr form)))
       ((or `(lambda . ,_) `(closure . ,_))
        ;; While byte-compile-unfold-bcf can inline dynbind byte-code into
@@ -300,7 +301,9 @@ Earlier variables shadow later ones with the same name.")
                ;; surrounded the `defsubst'.
                (byte-compile-warnings nil))
            (byte-compile name))
-         `(,(symbol-function name) ,@(cdr form))))
+         (let ((bc (symbol-function name)))
+           (byte-compile--check-arity-bytecode form bc)
+           `(,bc ,@(cdr form)))))
 
       (_ ;; Give up on inlining.
        form))))
index 2968f1af5df5e573b33ef730ca0cd671c99ddd98..f6150069e81dc7bac213b63c032a956f85aae335 100644 (file)
@@ -1477,6 +1477,30 @@ when printing the error message."
           (push (list f byte-compile-last-position nargs)
                 byte-compile-unresolved-functions)))))
 
+(defun byte-compile-emit-callargs-warn (name actual-args min-args max-args)
+  (byte-compile-set-symbol-position name)
+  (byte-compile-warn
+   "%s called with %d argument%s, but %s %s"
+   name actual-args
+   (if (= 1 actual-args) "" "s")
+   (if (< actual-args min-args)
+       "requires"
+     "accepts only")
+   (byte-compile-arglist-signature-string (cons min-args max-args))))
+
+(defun byte-compile--check-arity-bytecode (form bytecode)
+  "Check that the call in FORM matches that allowed by BYTECODE."
+  (when (and (byte-code-function-p bytecode)
+             (byte-compile-warning-enabled-p 'callargs))
+    (let* ((actual-args (length (cdr form)))
+           (arity (func-arity bytecode))
+           (min-args (car arity))
+           (max-args (and (numberp (cdr arity)) (cdr arity))))
+      (when (or (< actual-args min-args)
+                (and max-args (> actual-args max-args)))
+        (byte-compile-emit-callargs-warn
+         (car form) actual-args min-args max-args)))))
+
 ;; Warn if the form is calling a function with the wrong number of arguments.
 (defun byte-compile-callargs-warn (form)
   (let* ((def (or (byte-compile-fdefinition (car form) nil)
@@ -1491,16 +1515,9 @@ when printing the error message."
        (setcdr sig nil))
     (if sig
        (when (or (< ncall (car sig))
-               (and (cdr sig) (> ncall (cdr sig))))
-         (byte-compile-set-symbol-position (car form))
-         (byte-compile-warn
-          "%s called with %d argument%s, but %s %s"
-          (car form) ncall
-          (if (= 1 ncall) "" "s")
-          (if (< ncall (car sig))
-              "requires"
-            "accepts only")
-          (byte-compile-arglist-signature-string sig))))
+                 (and (cdr sig) (> ncall (cdr sig))))
+          (byte-compile-emit-callargs-warn
+           (car form) ncall (car sig) (cdr sig))))
     (byte-compile-format-warn form)
     (byte-compile-function-warn (car form) (length (cdr form)) def)))
 
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-callargs-defsubst.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-callargs-defsubst.el
new file mode 100644 (file)
index 0000000..3a29128
--- /dev/null
@@ -0,0 +1,5 @@
+;;; -*- lexical-binding: t -*-
+(defsubst warn-callargs-defsubst-f1 (_x)
+  nil)
+(defun warn-callargs-defsubst-f2 ()
+  (warn-callargs-defsubst-f1 1 2))
index 33413f5a002c29a06b43b2b2f3f8b564850f8109..7c40f7ebca3b8c3913226e14269096648ac47b0f 100644 (file)
@@ -700,6 +700,9 @@ byte-compiled.  Run with dynamic binding."
 (bytecomp--define-warning-file-test "warn-callargs.el"
                             "with 2 arguments, but accepts only 1")
 
+(bytecomp--define-warning-file-test "warn-callargs-defsubst.el"
+                            "with 2 arguments, but accepts only 1")
+
 (bytecomp--define-warning-file-test "warn-defcustom-nogroup.el"
                             "fails to specify containing group")