]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix mutates-arguments warning for `sort`
authorMattias EngdegÄrd <mattiase@acm.org>
Sun, 31 Mar 2024 14:12:45 +0000 (16:12 +0200)
committerEshel Yaron <me@eshelyaron.com>
Tue, 2 Apr 2024 13:24:07 +0000 (15:24 +0200)
* lisp/emacs-lisp/bytecomp.el (bytecomp--sort-call-in-place-p)
(bytecomp--mutargs-nconc, bytecomp--mutargs-sort): New.
(byte-compile-form, bytecomp--actually-important-return-value-p)
(mutating-fns):
Use a slightly more extendible scheme for specifying what arguments
a function mutates.  Give `sort` special treatment.

(cherry picked from commit 155462a1bd7909074f79a534324c7b209eb97142)

lisp/emacs-lisp/bytecomp.el

index 2b5eb34e57109fecc7a5688eb690daa930882740..5cff86784f07b2368e065b48666e8f0bf9f5c2f1 100644 (file)
@@ -3402,8 +3402,8 @@ lambda-expression."
                                       (t "."))))
           (let ((mutargs (function-get (car form) 'mutates-arguments)))
             (when mutargs
-              (dolist (idx (if (eq mutargs 'all-but-last)
-                               (number-sequence 1 (- (length form) 2))
+              (dolist (idx (if (symbolp mutargs)
+                               (funcall mutargs form)
                              mutargs))
                 (let ((arg (nth idx form)))
                   (when (and (or (and (eq (car-safe arg) 'quote)
@@ -3472,13 +3472,15 @@ lambda-expression."
       (if byte-compile--for-effect
           (byte-compile-discard)))))
 
+(defun bytecomp--sort-call-in-place-p (form)
+  (or (= (length form) 3)                  ; old-style
+      (plist-get (cddr form) :in-place)))  ; new-style
+
 (defun bytecomp--actually-important-return-value-p (form)
   "Whether FORM is really a call with a return value that should not go unused.
 This assumes the function has the `important-return-value' property."
   (cond ((eq (car form) 'sort)
-         ;; For `sort', we only care about non-destructive uses.
-         (and (zerop (% (length form) 2))  ; new-style call
-              (not (plist-get (cddr form) :in-place))))
+         (not (bytecomp--sort-call-in-place-p form)))
         (t t)))
 
 (let ((important-return-value-fns
@@ -3504,18 +3506,27 @@ This assumes the function has the `important-return-value' property."
   (dolist (fn important-return-value-fns)
     (put fn 'important-return-value t)))
 
+(defun bytecomp--mutargs-nconc (form)
+  ;; For `nconc', all arguments but the last are mutated.
+  (number-sequence 1 (- (length form) 2)))
+
+(defun bytecomp--mutargs-sort (form)
+  ;; For `sort', the first argument is mutated if the call is in-place.
+  (and (bytecomp--sort-call-in-place-p form) '(1)))
+
 (let ((mutating-fns
        ;; FIXME: Should there be a function declaration for this?
        ;;
        ;; (FUNC . ARGS) means that FUNC mutates arguments whose indices are
-       ;; in the list ARGS, starting at 1, or all but the last argument if
-       ;; ARGS is `all-but-last'.
+       ;; in the list ARGS, starting at 1.  ARGS can also be a function
+       ;; taking the function call form as argument and returning the
+       ;; list of indices.
        '(
          (setcar 1) (setcdr 1) (aset 1)
          (nreverse 1)
-         (nconc . all-but-last)
+         (nconc . bytecomp--mutargs-nconc)
          (nbutlast 1) (ntake 2)
-         (sort 1)
+         (sort  . bytecomp--mutargs-sort)
          (delq 2) (delete 2)
          (delete-dups 1) (delete-consecutive-dups 1)
          (plist-put 1)