diff options
| author | Mattias EngdegÄrd | 2022-12-14 17:48:17 +0100 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2022-12-14 19:30:16 +0100 |
| commit | 537f78b537ddd56198059bc02b5abc6e51c5b523 (patch) | |
| tree | f67ece8cc5bd33502d53bef2e37a35bfbb3b5b42 /test/lisp | |
| parent | 3b573f7d1f583d3c4169fa7d7dc1f4bcd22197c1 (diff) | |
| download | emacs-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.el | 54 |
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*") |