Skip to content

Commit f2071b6

Browse files
committed
Add the new macro with-suppressed-warnings
* lisp/emacs-lisp/byte-run.el (with-suppressed-warnings): New macro. * doc/lispref/compile.texi (Compiler Errors): Document with-suppressed-warnings and deemphasise with-no-warnings slightly. * lisp/emacs-lisp/bytecomp.el (byte-compile--suppressed-warnings): New internal variable. (byte-compile-warning-enabled-p): Heed byte-compile--suppressed-warnings, bound via with-suppressed-warnings. (byte-compile-initial-macro-environment): Provide a macro expansion of with-suppressed-warnings. (byte-compile-file-form-with-suppressed-warnings): New byte hunk handler for the suppressed symbol machinery. (byte-compile-suppressed-warnings): Ditto for the byteop. (byte-compile-file-form-defmumble): Ditto. (byte-compile-form, byte-compile-normal-call) (byte-compile-normal-call, byte-compile-variable-ref) (byte-compile-set-default, byte-compile-variable-set) (byte-compile-function-form, byte-compile-set-default) (byte-compile-warn-obsolete, byte-compile--declare-var): Pass the symbol being warned in to byte-compile-warning-enabled-p. * test/lisp/emacs-lisp/bytecomp-tests.el (test-suppression): New function. (bytecomp-test--with-suppressed-warnings): Tests.
1 parent b8350e5 commit f2071b6

File tree

5 files changed

+203
-27
lines changed

5 files changed

+203
-27
lines changed

doc/lispref/compile.texi

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -505,8 +505,25 @@ current lexical scope, or file if at top-level.) @xref{Defining
505505
Variables}.
506506
@end itemize
507507

508-
You can also suppress any and all compiler warnings within a certain
509-
expression using the construct @code{with-no-warnings}:
508+
You can also suppress compiler warnings within a certain expression
509+
using the @code{with-suppressed-warnings} macro:
510+
511+
@defspec with-suppressed-warnings warnings body@dots{}
512+
In execution, this is equivalent to @code{(progn @var{body}...)}, but
513+
the compiler does not issue warnings for the specified conditions in
514+
@var{body}. @var{warnings} is an associative list of warning symbols
515+
and function/variable symbols they apply to. For instance, if you
516+
wish to call an obsolete function called @code{foo}, but want to
517+
suppress the compilation warning, say:
518+
519+
@lisp
520+
(with-suppressed-warnings ((obsolete foo))
521+
(foo ...))
522+
@end lisp
523+
@end defspec
524+
525+
For more coarse-grained suppression of compiler warnings, you can use
526+
the @code{with-no-warnings} construct:
510527

511528
@c This is implemented with a defun, but conceptually it is
512529
@c a special form.
@@ -516,8 +533,9 @@ In execution, this is equivalent to @code{(progn @var{body}...)},
516533
but the compiler does not issue warnings for anything that occurs
517534
inside @var{body}.
518535

519-
We recommend that you use this construct around the smallest
520-
possible piece of code, to avoid missing possible warnings other than
536+
We recommend that you use @code{with-suppressed-warnings} instead, but
537+
if you do use this construct, that you use it around the smallest
538+
possible piece of code to avoid missing possible warnings other than
521539
one you intend to suppress.
522540
@end defspec
523541

etc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1692,6 +1692,10 @@ valid event type.
16921692

16931693
* Lisp Changes in Emacs 27.1
16941694

1695+
+++
1696+
** The new macro `with-suppressed-warnings' can be used to suppress
1697+
specific byte-compile warnings.
1698+
16951699
+++
16961700
** The 'append' arg of 'add-hook' is generalized to a finer notion of 'depth'
16971701
This makes it possible to control the ordering of functions more precisely,

lisp/emacs-lisp/byte-run.el

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,34 @@ is enabled."
494494
;; The implementation for the interpreter is basically trivial.
495495
(car (last body)))
496496

497+
(defmacro with-suppressed-warnings (_warnings &rest body)
498+
"Like `progn', but prevents compiler WARNINGS in BODY.
499+
500+
WARNINGS is an associative list where the first element of each
501+
item is a warning type, and the rest of the elements in each item
502+
are symbols they apply to. For instance, if you want to suppress
503+
byte compilation warnings about the two obsolete functions `foo'
504+
and `bar', as well as the function `zot' being called with the
505+
wrong number of parameters, say
506+
507+
\(with-suppressed-warnings ((obsolete foo bar)
508+
(callargs zot))
509+
(foo (bar))
510+
(zot 1 2))
511+
512+
The warnings that can be suppressed are a subset of the warnings
513+
in `byte-compile-warning-types'; see this variable for a fuller
514+
explanation of the warning types. The types that can be
515+
suppressed with this macro are `free-vars', `callargs',
516+
`redefine', `obsolete', `interactive-only', `lexical', `mapcar',
517+
`constants' and `suspicious'.
518+
519+
For the `mapcar' case, only the `mapcar' function can be used in
520+
the symbol list. For `suspicious', only `set-buffer' can be used."
521+
(declare (debug (sexp &optional body)) (indent 1))
522+
;; The implementation for the interpreter is basically trivial.
523+
`(progn ,@body))
524+
497525

498526
(defun byte-run--unescaped-character-literals-warning ()
499527
"Return a warning about unescaped character literals.

lisp/emacs-lisp/bytecomp.el

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -331,18 +331,27 @@ suppress. For example, (not mapcar) will suppress warnings about mapcar."
331331
,@(mapcar (lambda (x) `(const ,x))
332332
byte-compile-warning-types))))
333333

334+
(defvar byte-compile--suppressed-warnings nil
335+
"Dynamically bound by `with-suppressed-warnings' to suppress warnings.")
336+
334337
;;;###autoload
335338
(put 'byte-compile-warnings 'safe-local-variable
336339
(lambda (v)
337340
(or (symbolp v)
338341
(null (delq nil (mapcar (lambda (x) (not (symbolp x))) v))))))
339342

340-
(defun byte-compile-warning-enabled-p (warning)
343+
(defun byte-compile-warning-enabled-p (warning &optional symbol)
341344
"Return non-nil if WARNING is enabled, according to `byte-compile-warnings'."
342-
(or (eq byte-compile-warnings t)
343-
(if (eq (car byte-compile-warnings) 'not)
344-
(not (memq warning byte-compile-warnings))
345-
(memq warning byte-compile-warnings))))
345+
(let ((suppress nil))
346+
(dolist (elem byte-compile--suppressed-warnings)
347+
(when (and (eq (car elem) warning)
348+
(memq symbol (cdr elem)))
349+
(setq suppress t)))
350+
(and (not suppress)
351+
(or (eq byte-compile-warnings t)
352+
(if (eq (car byte-compile-warnings) 'not)
353+
(not (memq warning byte-compile-warnings))
354+
(memq warning byte-compile-warnings))))))
346355

347356
;;;###autoload
348357
(defun byte-compile-disable-warning (warning)
@@ -502,7 +511,16 @@ Return the compile-time value of FORM."
502511
form
503512
macroexpand-all-environment)))
504513
(eval expanded lexical-binding)
505-
expanded))))))
514+
expanded)))))
515+
(with-suppressed-warnings
516+
. ,(lambda (warnings &rest body)
517+
;; This function doesn't exist, but is just a placeholder
518+
;; symbol to hook up with the
519+
;; `byte-hunk-handler'/`byte-defop-compiler-1' machinery.
520+
`(internal--with-suppressed-warnings
521+
',warnings
522+
,(macroexpand-all `(progn ,@body)
523+
macroexpand-all-environment)))))
506524
"The default macro-environment passed to macroexpand by the compiler.
507525
Placing a macro here will cause a macro to have different semantics when
508526
expanded by the compiler as when expanded by the interpreter.")
@@ -1268,7 +1286,7 @@ function directly; use `byte-compile-warn' or
12681286

12691287
(defun byte-compile-warn-obsolete (symbol)
12701288
"Warn that SYMBOL (a variable or function) is obsolete."
1271-
(when (byte-compile-warning-enabled-p 'obsolete)
1289+
(when (byte-compile-warning-enabled-p 'obsolete symbol)
12721290
(let* ((funcp (get symbol 'byte-obsolete-info))
12731291
(msg (macroexp--obsolete-warning
12741292
symbol
@@ -2423,7 +2441,7 @@ list that represents a doc string reference.
24232441
(defun byte-compile--declare-var (sym)
24242442
(when (and (symbolp sym)
24252443
(not (string-match "[-*/:$]" (symbol-name sym)))
2426-
(byte-compile-warning-enabled-p 'lexical))
2444+
(byte-compile-warning-enabled-p 'lexical sym))
24272445
(byte-compile-warn "global/dynamic var `%s' lacks a prefix"
24282446
sym))
24292447
(when (memq sym byte-compile-lexical-variables)
@@ -2521,6 +2539,15 @@ list that represents a doc string reference.
25212539
(mapc 'byte-compile-file-form (cdr form))
25222540
nil))
25232541

2542+
(put 'internal--with-suppressed-warnings 'byte-hunk-handler
2543+
'byte-compile-file-form-with-suppressed-warnings)
2544+
(defun byte-compile-file-form-with-suppressed-warnings (form)
2545+
;; cf byte-compile-file-form-progn.
2546+
(let ((byte-compile--suppressed-warnings
2547+
(append (cadadr form) byte-compile--suppressed-warnings)))
2548+
(mapc 'byte-compile-file-form (cddr form))
2549+
nil))
2550+
25242551
;; Automatically evaluate define-obsolete-function-alias etc at top-level.
25252552
(put 'make-obsolete 'byte-hunk-handler 'byte-compile-file-form-make-obsolete)
25262553
(defun byte-compile-file-form-make-obsolete (form)
@@ -2559,7 +2586,7 @@ not to take responsibility for the actual compilation of the code."
25592586
(setq byte-compile-call-tree
25602587
(cons (list name nil nil) byte-compile-call-tree))))
25612588

2562-
(if (byte-compile-warning-enabled-p 'redefine)
2589+
(if (byte-compile-warning-enabled-p 'redefine name)
25632590
(byte-compile-arglist-warn name arglist macro))
25642591

25652592
(if byte-compile-verbose
@@ -2571,15 +2598,15 @@ not to take responsibility for the actual compilation of the code."
25712598
;; This also silences "multiple definition" warnings for defmethods.
25722599
nil)
25732600
(that-one
2574-
(if (and (byte-compile-warning-enabled-p 'redefine)
2601+
(if (and (byte-compile-warning-enabled-p 'redefine name)
25752602
;; Don't warn when compiling the stubs in byte-run...
25762603
(not (assq name byte-compile-initial-macro-environment)))
25772604
(byte-compile-warn
25782605
"`%s' defined multiple times, as both function and macro"
25792606
name))
25802607
(setcdr that-one nil))
25812608
(this-one
2582-
(when (and (byte-compile-warning-enabled-p 'redefine)
2609+
(when (and (byte-compile-warning-enabled-p 'redefine name)
25832610
;; Hack: Don't warn when compiling the magic internal
25842611
;; byte-compiler macros in byte-run.el...
25852612
(not (assq name byte-compile-initial-macro-environment)))
@@ -2588,7 +2615,7 @@ not to take responsibility for the actual compilation of the code."
25882615
name)))
25892616
((eq (car-safe (symbol-function name))
25902617
(if macro 'lambda 'macro))
2591-
(when (byte-compile-warning-enabled-p 'redefine)
2618+
(when (byte-compile-warning-enabled-p 'redefine name)
25922619
(byte-compile-warn "%s `%s' being redefined as a %s"
25932620
(if macro "function" "macro")
25942621
name
@@ -3153,7 +3180,7 @@ for symbols generated by the byte compiler itself."
31533180
(when (and (byte-compile-warning-enabled-p 'suspicious)
31543181
(macroexp--const-symbol-p fn))
31553182
(byte-compile-warn "`%s' called as a function" fn))
3156-
(when (and (byte-compile-warning-enabled-p 'interactive-only)
3183+
(when (and (byte-compile-warning-enabled-p 'interactive-only fn)
31573184
interactive-only)
31583185
(byte-compile-warn "`%s' is for interactive use only%s"
31593186
fn
@@ -3194,8 +3221,8 @@ for symbols generated by the byte compiler itself."
31943221
(byte-compile-discard))))
31953222

31963223
(defun byte-compile-normal-call (form)
3197-
(when (and (byte-compile-warning-enabled-p 'callargs)
3198-
(symbolp (car form)))
3224+
(when (and (symbolp (car form))
3225+
(byte-compile-warning-enabled-p 'callargs (car form)))
31993226
(if (memq (car form)
32003227
'(custom-declare-group custom-declare-variable
32013228
custom-declare-face))
@@ -3204,7 +3231,7 @@ for symbols generated by the byte compiler itself."
32043231
(if byte-compile-generate-call-tree
32053232
(byte-compile-annotate-call-tree form))
32063233
(when (and byte-compile--for-effect (eq (car form) 'mapcar)
3207-
(byte-compile-warning-enabled-p 'mapcar))
3234+
(byte-compile-warning-enabled-p 'mapcar 'mapcar))
32083235
(byte-compile-set-symbol-position 'mapcar)
32093236
(byte-compile-warn
32103237
"`mapcar' called for effect; use `mapc' or `dolist' instead"))
@@ -3340,7 +3367,8 @@ for symbols generated by the byte compiler itself."
33403367
(when (symbolp var)
33413368
(byte-compile-set-symbol-position var))
33423369
(cond ((or (not (symbolp var)) (macroexp--const-symbol-p var))
3343-
(when (byte-compile-warning-enabled-p 'constants)
3370+
(when (byte-compile-warning-enabled-p 'constants
3371+
(and (symbolp var) var))
33443372
(byte-compile-warn (if (eq access-type 'let-bind)
33453373
"attempt to let-bind %s `%s'"
33463374
"variable reference to %s `%s'")
@@ -3377,7 +3405,7 @@ for symbols generated by the byte compiler itself."
33773405
;; VAR is lexically bound
33783406
(byte-compile-stack-ref (cdr lex-binding))
33793407
;; VAR is dynamically bound
3380-
(unless (or (not (byte-compile-warning-enabled-p 'free-vars))
3408+
(unless (or (not (byte-compile-warning-enabled-p 'free-vars var))
33813409
(boundp var)
33823410
(memq var byte-compile-bound-variables)
33833411
(memq var byte-compile-free-references))
@@ -3393,7 +3421,7 @@ for symbols generated by the byte compiler itself."
33933421
;; VAR is lexically bound.
33943422
(byte-compile-stack-set (cdr lex-binding))
33953423
;; VAR is dynamically bound.
3396-
(unless (or (not (byte-compile-warning-enabled-p 'free-vars))
3424+
(unless (or (not (byte-compile-warning-enabled-p 'free-vars var))
33973425
(boundp var)
33983426
(memq var byte-compile-bound-variables)
33993427
(memq var byte-compile-free-assignments))
@@ -3878,7 +3906,7 @@ discarding."
38783906
(defun byte-compile-function-form (form)
38793907
(let ((f (nth 1 form)))
38803908
(when (and (symbolp f)
3881-
(byte-compile-warning-enabled-p 'callargs))
3909+
(byte-compile-warning-enabled-p 'callargs f))
38823910
(byte-compile-function-warn f t (byte-compile-fdefinition f nil)))
38833911

38843912
(byte-compile-constant (if (eq 'lambda (car-safe f))
@@ -3948,7 +3976,8 @@ discarding."
39483976
(let ((var (car-safe (cdr varexp))))
39493977
(and (or (not (symbolp var))
39503978
(macroexp--const-symbol-p var t))
3951-
(byte-compile-warning-enabled-p 'constants)
3979+
(byte-compile-warning-enabled-p 'constants
3980+
(and (symbolp var) var))
39523981
(byte-compile-warn
39533982
"variable assignment to %s `%s'"
39543983
(if (symbolp var) "constant" "nonvariable")
@@ -4609,7 +4638,7 @@ binding slots have been popped."
46094638

46104639
(defun byte-compile-save-excursion (form)
46114640
(if (and (eq 'set-buffer (car-safe (car-safe (cdr form))))
4612-
(byte-compile-warning-enabled-p 'suspicious))
4641+
(byte-compile-warning-enabled-p 'suspicious 'set-buffer))
46134642
(byte-compile-warn
46144643
"Use `with-current-buffer' rather than save-excursion+set-buffer"))
46154644
(byte-compile-out 'byte-save-excursion 0)
@@ -4650,7 +4679,7 @@ binding slots have been popped."
46504679
;; This is not used for file-level defvar/consts.
46514680
(when (and (symbolp (nth 1 form))
46524681
(not (string-match "[-*/:$]" (symbol-name (nth 1 form))))
4653-
(byte-compile-warning-enabled-p 'lexical))
4682+
(byte-compile-warning-enabled-p 'lexical (nth 1 form)))
46544683
(byte-compile-warn "global/dynamic var `%s' lacks a prefix"
46554684
(nth 1 form)))
46564685
(let ((fun (nth 0 form))
@@ -4767,6 +4796,13 @@ binding slots have been popped."
47674796
(let (byte-compile-warnings)
47684797
(byte-compile-form (cons 'progn (cdr form)))))
47694798

4799+
(byte-defop-compiler-1 internal--with-suppressed-warnings
4800+
byte-compile-suppressed-warnings)
4801+
(defun byte-compile-suppressed-warnings (form)
4802+
(let ((byte-compile--suppressed-warnings
4803+
(append (cadadr form) byte-compile--suppressed-warnings)))
4804+
(byte-compile-form (macroexp-progn (cddr form)))))
4805+
47704806
;; Warn about misuses of make-variable-buffer-local.
47714807
(byte-defop-compiler-1 make-variable-buffer-local
47724808
byte-compile-make-variable-buffer-local)

0 commit comments

Comments
 (0)