summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp')
-rw-r--r--lisp/emacs-lisp/bytecomp.el29
-rw-r--r--lisp/emacs-lisp/eieio.el2
-rw-r--r--lisp/emacs-lisp/ert.el41
-rw-r--r--lisp/emacs-lisp/gv.el7
-rw-r--r--lisp/emacs-lisp/testcover.el10
5 files changed, 71 insertions, 18 deletions
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 5fa7389e431..9e14c91c953 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -1572,6 +1572,7 @@ extra args."
;; macroenvironment.
(copy-alist byte-compile-initial-macro-environment))
(byte-compile--outbuffer nil)
+ (overriding-plist-environment nil)
(byte-compile-function-environment nil)
(byte-compile-bound-variables nil)
(byte-compile-lexical-variables nil)
@@ -4714,6 +4715,34 @@ binding slots have been popped."
'byte-hunk-handler 'byte-compile-form-make-variable-buffer-local)
(defun byte-compile-form-make-variable-buffer-local (form)
(byte-compile-keep-pending form 'byte-compile-normal-call))
+
+(put 'function-put 'byte-hunk-handler 'byte-compile-define-symbol-prop)
+(put 'define-symbol-prop 'byte-hunk-handler 'byte-compile-define-symbol-prop)
+(defun byte-compile-define-symbol-prop (form)
+ (pcase form
+ ((and `(,op ,fun ,prop ,val)
+ (guard (and (macroexp-const-p fun)
+ (macroexp-const-p prop)
+ (or (macroexp-const-p val)
+ ;; Also accept anonymous functions, since
+ ;; we're at top-level which implies they're
+ ;; also constants.
+ (pcase val (`(function (lambda . ,_)) t))))))
+ (byte-compile-push-constant op)
+ (byte-compile-form fun)
+ (byte-compile-form prop)
+ (let* ((fun (eval fun))
+ (prop (eval prop))
+ (val (if (macroexp-const-p val)
+ (eval val)
+ (byte-compile-lambda (cadr val)))))
+ (push `(,fun
+ . (,prop ,val ,@(alist-get fun overriding-plist-environment)))
+ overriding-plist-environment)
+ (byte-compile-push-constant val)
+ (byte-compile-out 'byte-call 3)))
+
+ (_ (byte-compile-keep-pending form))))
;;; tags
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el
index 1a7de55fcef..8b92d5b7acd 100644
--- a/lisp/emacs-lisp/eieio.el
+++ b/lisp/emacs-lisp/eieio.el
@@ -246,7 +246,7 @@ This method is obsolete."
;; test, so we can let typep have the CLOS documented behavior
;; while keeping our above predicate clean.
- (put ',name 'cl-deftype-satisfies #',testsym2)
+ (define-symbol-prop ',name 'cl-deftype-satisfies #',testsym2)
(eieio-defclass-internal ',name ',superclasses ',slots ',options-and-doc)
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index d7bd331c11b..c232b08bd1a 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -260,6 +260,14 @@ DATA is displayed to the user and should state the reason for skipping."
(when ert--should-execution-observer
(funcall ert--should-execution-observer form-description)))
+;; See Bug#24402 for why this exists
+(defun ert--should-signal-hook (error-symbol data)
+ "Stupid hack to stop `condition-case' from catching ert signals.
+It should only be stopped when ran from inside ert--run-test-internal."
+ (when (and (not (symbolp debugger)) ; only run on anonymous debugger
+ (memq error-symbol '(ert-test-failed ert-test-skipped)))
+ (funcall debugger 'error data)))
+
(defun ert--special-operator-p (thing)
"Return non-nil if THING is a symbol naming a special operator."
(and (symbolp thing)
@@ -267,16 +275,22 @@ DATA is displayed to the user and should state the reason for skipping."
(and (subrp definition)
(eql (cdr (subr-arity definition)) 'unevalled)))))
+;; FIXME: Code inside of here should probably be evaluated like it is
+;; outside of tests, with the sole exception of error handling
(defun ert--expand-should-1 (whole form inner-expander)
"Helper function for the `should' macro and its variants."
(let ((form
- (macroexpand form (append (bound-and-true-p
- byte-compile-macro-environment)
- (cond
- ((boundp 'macroexpand-all-environment)
- macroexpand-all-environment)
- ((boundp 'cl-macro-environment)
- cl-macro-environment))))))
+ ;; catch macroexpansion errors
+ (condition-case err
+ (macroexpand-all form
+ (append (bound-and-true-p
+ byte-compile-macro-environment)
+ (cond
+ ((boundp 'macroexpand-all-environment)
+ macroexpand-all-environment)
+ ((boundp 'cl-macro-environment)
+ cl-macro-environment))))
+ (error `(signal ',(car err) ',(cdr err))))))
(cond
((or (atom form) (ert--special-operator-p (car form)))
(let ((value (cl-gensym "value-")))
@@ -297,8 +311,13 @@ DATA is displayed to the user and should state the reason for skipping."
(args (cl-gensym "args-"))
(value (cl-gensym "value-"))
(default-value (cl-gensym "ert-form-evaluation-aborted-")))
- `(let ((,fn (function ,fn-name))
- (,args (list ,@arg-forms)))
+ `(let* ((,fn (function ,fn-name))
+ (,args (condition-case err
+ (let ((signal-hook-function #'ert--should-signal-hook))
+ (list ,@arg-forms))
+ (error (progn (setq ,fn #'signal)
+ (list (car err)
+ (cdr err)))))))
(let ((,value ',default-value))
,(funcall inner-expander
`(setq ,value (apply ,fn ,args))
@@ -760,6 +779,10 @@ This mainly sets up debugger-related bindings."
;; too expensive, we can remove it.
(with-temp-buffer
(save-window-excursion
+ ;; FIXME: Use `signal-hook-function' instead of `debugger' to
+ ;; handle ert errors. Once that's done, remove
+ ;; `ert--should-signal-hook'. See Bug#24402 and Bug#11218 for
+ ;; details.
(let ((debugger (lambda (&rest args)
(ert--run-test-debugger test-execution-info
args)))
diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el
index 27376fc7f95..a8b8974cb4f 100644
--- a/lisp/emacs-lisp/gv.el
+++ b/lisp/emacs-lisp/gv.el
@@ -146,12 +146,7 @@ NAME is a symbol: the name of a function, macro, or special form.
HANDLER is a function which takes an argument DO followed by the same
arguments as NAME. DO is a function as defined in `gv-get'."
(declare (indent 1) (debug (sexp form)))
- ;; Use eval-and-compile so the method can be used in the same file as it
- ;; is defined.
- ;; FIXME: Just like byte-compile-macro-environment, we should have something
- ;; like byte-compile-symbolprop-environment so as to handle these things
- ;; cleanly without affecting the running Emacs.
- `(eval-and-compile (put ',name 'gv-expander ,handler)))
+ `(function-put ',name 'gv-expander ,handler))
;;;###autoload
(defun gv--defun-declaration (symbol name args handler &optional fix)
diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el
index 433ad38a147..17891fd6096 100644
--- a/lisp/emacs-lisp/testcover.el
+++ b/lisp/emacs-lisp/testcover.el
@@ -463,7 +463,10 @@ binding `testcover-vector' to the code-coverage vector for TESTCOVER-SYM
(cond
((eq (aref testcover-vector idx) 'unknown)
(aset testcover-vector idx val))
- ((not (equal (aref testcover-vector idx) val))
+ ((not (condition-case ()
+ (equal (aref testcover-vector idx) val)
+ ;; TODO: Actually check circular lists for equality.
+ (circular-list nil)))
(aset testcover-vector idx 'ok-coverage)))
val)
@@ -475,7 +478,10 @@ same value during coverage testing."
((eq (aref testcover-vector idx) '1value)
(aset testcover-vector idx (cons '1value val)))
((not (and (eq (car-safe (aref testcover-vector idx)) '1value)
- (equal (cdr (aref testcover-vector idx)) val)))
+ (condition-case ()
+ (equal (cdr (aref testcover-vector idx)) val)
+ ;; TODO: Actually check circular lists for equality.
+ (circular-list nil))))
(error "Value of form marked with `1value' does vary: %s" val)))
val)