Edebug: Disable backtracking when hitting a &define keyword.

Edebug doesn't deal well with backtracking out of definitions, see
Bug#41988.  Rather than trying to support this rare situation (e.g. by
implementing a multipass parser), prevent it by adding an implicit
gate.

* lisp/emacs-lisp/edebug.el (edebug--match-&-spec-op): Disable
backtracking when hitting a &define keyword.

* test/lisp/emacs-lisp/edebug-tests.el
(edebug-tests-duplicate-&define): New unit test.
(edebug-tests--duplicate-&define): New helper macro.

* doc/lispref/edebug.texi (Backtracking): Mention &define in the list
of constructs that disable backtracking.

* etc/NEWS: Document new behavior.
This commit is contained in:
Philipp Stephani 2021-03-18 12:40:08 +01:00
parent b72571ca49
commit 53dfd85a7f
4 changed files with 43 additions and 13 deletions

View file

@ -1942,14 +1942,16 @@ a sequence of elements."
;; Normally, &define is interpreted specially other places.
;; This should only be called inside of a spec list to match the remainder
;; of the current list. e.g. ("lambda" &define args def-body)
(edebug-make-form-wrapper
cursor
(edebug-before-offset cursor)
;; Find the last offset in the list.
(let ((offsets (edebug-cursor-offsets cursor)))
(while (consp offsets) (setq offsets (cdr offsets)))
offsets)
specs))
(prog1 (edebug-make-form-wrapper
cursor
(edebug-before-offset cursor)
;; Find the last offset in the list.
(let ((offsets (edebug-cursor-offsets cursor)))
(while (consp offsets) (setq offsets (cdr offsets)))
offsets)
specs)
;; Stop backtracking here (Bug#41988).
(setq edebug-gate t)))
(cl-defmethod edebug--match-&-spec-op ((_ (eql &name)) cursor specs)
"Compute the name for `&name SPEC FUN` spec operator.