aboutsummaryrefslogtreecommitdiffstats
path: root/test/lisp
diff options
context:
space:
mode:
authorMattias EngdegÄrd2022-12-14 17:48:17 +0100
committerMattias EngdegÄrd2022-12-14 19:30:16 +0100
commit537f78b537ddd56198059bc02b5abc6e51c5b523 (patch)
treef67ece8cc5bd33502d53bef2e37a35bfbb3b5b42 /test/lisp
parent3b573f7d1f583d3c4169fa7d7dc1f4bcd22197c1 (diff)
downloademacs-537f78b537ddd56198059bc02b5abc6e51c5b523.tar.gz
emacs-537f78b537ddd56198059bc02b5abc6e51c5b523.zip
Warn about unmatchable constant args to `eq`, `memq` etc
Add a byte-compiler warning about attempts to compare literal values with undefined identity relation to other values. For example: (eq x 2.0) (memq x '("a" (b) [c])) Such incomparable values include all literal conses, strings, vectors, records and (except for eql and memql) floats and bignums. The warning currently applies to eq, eql, memq, memql, assq, rassq, remq and delq. * lisp/emacs-lisp/bytecomp.el (bytecomp--dodgy-eq-arg) (bytecomp--value-type-description, bytecomp--arg-type-description) (bytecomp--warn-dodgy-eq-arg, bytecomp--check-eq-args) (bytecomp--check-memq-args): New. (eq, eql, memq, memql, assq, rassq, remq, delq): Set compiler-macro property. * lisp/emacs-lisp/byte-run.el (with-suppressed-warnings): Amend doc string. * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp--with-warning-test): Fix text-quoting-style and expand re-warning so that it doesn't need to be a literal. (bytecomp-warn-dodgy-args-eq, bytecomp-warn-dodgy-args-memq): New tests.
Diffstat (limited to 'test/lisp')
-rw-r--r--test/lisp/emacs-lisp/bytecomp-tests.el54
1 files changed, 51 insertions, 3 deletions
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el
index e7c308213e4..00361a4286b 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -837,9 +837,11 @@ byte-compiled. Run with dynamic binding."
837 (declare (indent 1)) 837 (declare (indent 1))
838 `(with-current-buffer (get-buffer-create "*Compile-Log*") 838 `(with-current-buffer (get-buffer-create "*Compile-Log*")
839 (let ((inhibit-read-only t)) (erase-buffer)) 839 (let ((inhibit-read-only t)) (erase-buffer))
840 (byte-compile ,@form) 840 (let ((text-quoting-style 'grave))
841 (ert-info ((prin1-to-string (buffer-string)) :prefix "buffer: ") 841 (byte-compile ,@form)
842 (should (re-search-forward ,(string-replace " " "[ \n]+" re-warning)))))) 842 (ert-info ((prin1-to-string (buffer-string)) :prefix "buffer: ")
843 (should (re-search-forward
844 (string-replace " " "[ \n]+" ,re-warning)))))))
843 845
844(ert-deftest bytecomp-warn-wrong-args () 846(ert-deftest bytecomp-warn-wrong-args ()
845 (bytecomp--with-warning-test "remq.*3.*2" 847 (bytecomp--with-warning-test "remq.*3.*2"
@@ -863,6 +865,52 @@ byte-compiled. Run with dynamic binding."
863 (bytecomp--with-warning-test "defvar.*foo.*wider than.*characters" 865 (bytecomp--with-warning-test "defvar.*foo.*wider than.*characters"
864 `(defvar foo t ,bytecomp-tests--docstring))) 866 `(defvar foo t ,bytecomp-tests--docstring)))
865 867
868(ert-deftest bytecomp-warn-dodgy-args-eq ()
869 (dolist (fn '(eq eql))
870 (cl-flet ((msg (type arg)
871 (format
872 "`%s' called with literal %s that may never match (arg %d)"
873 fn type arg)))
874 (bytecomp--with-warning-test (msg "list" 1) `(,fn '(a) 'x))
875 (bytecomp--with-warning-test (msg "string" 2) `(,fn 'x "a"))
876 (bytecomp--with-warning-test (msg "vector" 2) `(,fn 'x [a]))
877 (unless (eq fn 'eql)
878 (bytecomp--with-warning-test (msg "integer" 2) `(,fn 'x #x10000000000))
879 (bytecomp--with-warning-test (msg "float" 2) `(,fn 'x 1.0))))))
880
881(ert-deftest bytecomp-warn-dodgy-args-memq ()
882 (dolist (fn '(memq memql remq delq assq rassq))
883 (cl-labels
884 ((msg1 (type)
885 (format
886 "`%s' called with literal %s that may never match (arg 1)"
887 fn type))
888 (msg2 (type)
889 (format
890 "`%s' called with literal %s that may never match (element 2 of arg 2)"
891 fn type))
892 (lst (elt)
893 (cond ((eq fn 'assq) `((a . 1) (,elt . 2) (c . 3)))
894 ((eq fn 'rassq) `((1 . a) (2 . ,elt) (3 . c)))
895 (t `(a ,elt c))))
896 (form2 (elt)
897 `(,fn 'x ',(lst elt))))
898
899 (bytecomp--with-warning-test (msg1 "list") `(,fn '(a) '(x)))
900 (bytecomp--with-warning-test (msg1 "string") `(,fn "a" '(x)))
901 (bytecomp--with-warning-test (msg1 "vector") `(,fn [a] '(x)))
902 (unless (eq fn 'memql)
903 (bytecomp--with-warning-test (msg1 "integer") `(,fn #x10000000000 '(x)))
904 (bytecomp--with-warning-test (msg1 "float") `(,fn 1.0 '(x))))
905
906 (bytecomp--with-warning-test (msg2 "list") (form2 '(b)))
907 (bytecomp--with-warning-test (msg2 "list") (form2 ''b))
908 (bytecomp--with-warning-test (msg2 "string") (form2 "b"))
909 (bytecomp--with-warning-test (msg2 "vector") (form2 [b]))
910 (unless (eq fn 'memql)
911 (bytecomp--with-warning-test (msg2 "integer") (form2 #x10000000000))
912 (bytecomp--with-warning-test (msg2 "float") (form2 1.0))))))
913
866(defmacro bytecomp--define-warning-file-test (file re-warning &optional reverse) 914(defmacro bytecomp--define-warning-file-test (file re-warning &optional reverse)
867 `(ert-deftest ,(intern (format "bytecomp/%s" file)) () 915 `(ert-deftest ,(intern (format "bytecomp/%s" file)) ()
868 (with-current-buffer (get-buffer-create "*Compile-Log*") 916 (with-current-buffer (get-buffer-create "*Compile-Log*")