diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 842697c7245..10a50da4628 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -225,6 +225,14 @@ (byte-compile-log-lap-1 ,format-string ,@args))) +(defvar byte-optimize--lexvars nil + "Lexical variables in scope, in reverse order of declaration. +Each element is on the form (NAME KEEP [VALUE]), where: + NAME is the variable name, + KEEP is a boolean indicating whether the binding must be retained, + VALUE, if present, is a substitutable expression. +Earlier variables shadow later ones with the same name.") + ;;; byte-compile optimizers to support inlining (put 'inline 'byte-optimizer #'byte-optimize-inline-handler) @@ -268,19 +276,29 @@ ;; The byte-code will be really inlined in byte-compile-unfold-bcf. `(,fn ,@(cdr form))) ((or `(lambda . ,_) `(closure . ,_)) - (if (eq fn localfn) ;From the same file => same mode. + ;; While byte-compile-unfold-bcf can inline dynbind byte-code into + ;; letbind byte-code (or any other combination for that matter), we + ;; can only inline dynbind source into dynbind source or letbind + ;; source into letbind source. + ;; When the function comes from another file, we byte-compile + ;; the inlined function first, and then inline its byte-code. + ;; This also has the advantage that the final code does not + ;; depend on the order of compilation of ELisp files, making + ;; the build more reproducible. + (if (eq fn localfn) + ;; From the same file => same mode. (macroexp--unfold-lambda `(,fn ,@(cdr form))) - ;; While byte-compile-unfold-bcf can inline dynbind byte-code into - ;; letbind byte-code (or any other combination for that matter), we - ;; can only inline dynbind source into dynbind source or letbind - ;; source into letbind source. - ;; We can of course byte-compile the inlined function - ;; first, and then inline its byte-code. This also has the advantage - ;; that the final code does not depend on the order of compilation - ;; of ELisp files, making the build more reproducible. ;; Since we are called from inside the optimiser, we need to make ;; sure not to propagate lexvar values. - (dlet ((byte-optimize--lexvars nil)) + (let ((byte-optimize--lexvars nil) + ;; Silence all compilation warnings: the useful ones should + ;; be displayed when the function's source file will be + ;; compiled anyway, but more importantly we would otherwise + ;; emit spurious warnings here because we don't have the full + ;; context, such as `declare-functions' placed earlier in the + ;; source file's code or `with-suppressed-warnings' that + ;; surrounded the `defsubst'. + (byte-compile-warnings nil)) (byte-compile name)) `(,(symbol-function name) ,@(cdr form)))) @@ -297,14 +315,6 @@ This does usually not indicate a problem and makes the compiler very chatty, but can be useful for debugging.") -(defvar byte-optimize--lexvars nil - "Lexical variables in scope, in reverse order of declaration. -Each element is on the form (NAME KEEP [VALUE]), where: - NAME is the variable name, - KEEP is a boolean indicating whether the binding must be retained, - VALUE, if present, is a substitutable expression. -Earlier variables shadow later ones with the same name.") - (defvar byte-optimize--vars-outside-condition nil "Alist of variables lexically bound outside conditionally executed code. Variables here are sensitive to mutation inside the conditional code,