]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix (setf (map-elt map key) (my-func))
authorLars Ingebrigtsen <larsi@gnus.org>
Wed, 1 Sep 2021 08:32:49 +0000 (10:32 +0200)
committerLars Ingebrigtsen <larsi@gnus.org>
Wed, 1 Sep 2021 08:32:49 +0000 (10:32 +0200)
* lisp/emacs-lisp/map.el (map-elt): Ensure that the value isn't
referenced more than once (bug#50290).

lisp/emacs-lisp/map.el
test/lisp/emacs-lisp/map-tests.el

index 988a62a4e34cb6982c05d300363d419440dce20f..77431f0c594d0e3b7050c526306e479a8d44753e 100644 (file)
@@ -119,14 +119,16 @@ or array."
             ((key key) (default default) (testfn testfn))
           (funcall do `(map-elt ,mgetter ,key ,default)
                    (lambda (v)
-                     `(condition-case nil
-                          ;; Silence warnings about the hidden 4th arg.
-                          (with-no-warnings (map-put! ,mgetter ,key ,v ,testfn))
-                        (map-not-inplace
-                         ,(funcall msetter
-                                   `(map-insert ,mgetter ,key ,v))
-                         ;; Always return the value.
-                         ,v))))))))
+                     (macroexp-let2 nil v v
+                       `(condition-case nil
+                            ;; Silence warnings about the hidden 4th arg.
+                            (with-no-warnings
+                              (map-put! ,mgetter ,key ,v ,testfn))
+                          (map-not-inplace
+                           ,(funcall msetter
+                                     `(map-insert ,mgetter ,key ,v))
+                           ;; Always return the value.
+                           ,v)))))))))
    ;; `testfn' is deprecated.
    (advertised-calling-convention (map key &optional default) "27.1"))
   ;; Can't use `cl-defmethod' with `advertised-calling-convention'.
index 658ed2e7119fe15bc777f538cba7eb4fcee346fa..c0f0dbc92be31664d29641f1e4ab5181c232339e 100644 (file)
@@ -521,5 +521,14 @@ Evaluate BODY for each created map."
                   'value2))
     (should (equal (map-elt ht 'key) 'value2))))
 
+(ert-deftest test-setf-map-with-function ()
+  (let ((num 0)
+        (map nil))
+    (setf (map-elt map 'foo)
+          (funcall (lambda ()
+                     (cl-incf num))))
+    ;; Check that the function is only called once.
+    (should (= num 1))))
+
 (provide 'map-tests)
 ;;; map-tests.el ends here