diff options
-rw-r--r-- | doc/lispref/errors.texi | 7 | ||||
-rw-r--r-- | doc/lispref/tips.texi | 14 | ||||
-rw-r--r-- | doc/lispref/variables.texi | 13 | ||||
-rw-r--r-- | lisp/emacs-lisp/cl-macs.el | 2 | ||||
-rw-r--r-- | lisp/emacs-lisp/edebug.el | 67 | ||||
-rw-r--r-- | lisp/emacs-lisp/subr-x.el | 8 | ||||
-rw-r--r-- | lisp/net/tramp.el | 5 | ||||
-rw-r--r-- | lisp/tree-widget.el | 2 | ||||
-rw-r--r-- | src/buffer.c | 2 | ||||
-rw-r--r-- | src/bytecode.c | 6 | ||||
-rw-r--r-- | src/data.c | 6 | ||||
-rw-r--r-- | src/font.c | 9 | ||||
-rw-r--r-- | test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el | 4 | ||||
-rw-r--r-- | test/lisp/emacs-lisp/edebug-tests.el | 14 | ||||
-rw-r--r-- | test/lisp/emacs-lisp/subr-x-tests.el | 2 | ||||
-rw-r--r-- | test/lisp/net/tramp-tests.el | 44 |
16 files changed, 143 insertions, 62 deletions
diff --git a/doc/lispref/errors.texi b/doc/lispref/errors.texi index 1f67819c34e..cd22b70800d 100644 --- a/doc/lispref/errors.texi +++ b/doc/lispref/errors.texi @@ -172,8 +172,11 @@ The message is @samp{Search failed}. @xref{Searching and Matching}. @item setting-constant The message is @samp{Attempt to set a constant symbol}. This happens -when attempting to assign values to @code{nil}, @code{t}, and keyword -symbols. @xref{Constant Variables}. +when attempting to assign values to @code{nil}, @code{t}, +@code{most-positive-fixnum}, @code{most-negative-fixnum}, and keyword +symbols. It also happens when attempting to assign values to +@code{enable-multibyte-characters} and some other symbols whose direct +assignment is not allowed for some reason. @xref{Constant Variables}. @c simple.el @item text-read-only diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi index 17fd4a1027e..42a68677f58 100644 --- a/doc/lispref/tips.texi +++ b/doc/lispref/tips.texi @@ -534,9 +534,17 @@ that you know @emph{will} be defined, use a @code{declare-function} statement (@pxref{Declaring Functions}). @item -If you use many functions and variables from a certain file, you can -add a @code{require} for that package to avoid compilation warnings -for them. For instance, +If you use many functions, macros, and variables from a certain file, +you can add a @code{require} (@pxref{Named Features, require}) for +that package to avoid compilation warnings for them, like this: + +@example +(require 'foo) +@end example + +@noindent +If you need only macros from some file, you can require it only at +compile time (@pxref{Eval During Compile}). For instance, @example (eval-when-compile diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi index 99bbfc91243..a871352b004 100644 --- a/doc/lispref/variables.texi +++ b/doc/lispref/variables.texi @@ -139,6 +139,13 @@ Variables}). A @code{defconst} form serves to inform human readers that you do not intend to change the value of a variable, but Emacs does not raise an error if you actually change it. +@cindex read-only variables +A small number of additional symbols are made read-only for various +practical reasons. These include @code{enable-multibyte-characters}, +@code{most-positive-fixnum}, @code{most-negative-fixnum}, and a few +others. Any attempt to set or bind these also signals a +@code{setting-constant} error. + @node Local Variables @section Local Variables @cindex binding local variables @@ -1355,6 +1362,9 @@ is not current either on entry to or exit from the @code{let}. This is because @code{let} does not distinguish between different kinds of bindings; it knows only which variable the binding was made for. +It is an error to make a constant or a read-only variable +buffer-local. @xref{Constant Variables}. + If the variable is terminal-local (@pxref{Multiple Terminals}), this function signals an error. Such variables cannot have buffer-local bindings as well. @@ -1394,6 +1404,9 @@ in a void buffer-local value and leave the default value unaffected. The value returned is @var{variable}. +It is an error to make a constant or a read-only variable +buffer-local. @xref{Constant Variables}. + @strong{Warning:} Don't assume that you should use @code{make-variable-buffer-local} for user-option variables, simply because users @emph{might} want to customize them differently in diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 10792aefdcc..f5311041cce 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -694,7 +694,7 @@ its argument list allows full Common Lisp conventions." (defmacro cl-destructuring-bind (args expr &rest body) "Bind the variables in ARGS to the result of EXPR and execute BODY." (declare (indent 2) - (debug (&define cl-macro-list def-form cl-declarations def-body))) + (debug (&define cl-macro-list1 def-form cl-declarations def-body))) (let* ((cl--bind-lets nil) (cl--bind-forms nil) (cl--bind-defs nil) (cl--bind-block 'cl-none) (cl--bind-enquote nil)) (cl--do-arglist (or args '(&aux)) expr) diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index 0e8f77e29a8..dec986ae3e3 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -950,7 +950,8 @@ circular objects. Let `read' read everything else." ;;; Cursors for traversal of list and vector elements with offsets. -(defvar edebug-dotted-spec nil) +(defvar edebug-dotted-spec nil + "Set to t when matching after the dot in a dotted spec list.") (defun edebug-new-cursor (expressions offsets) ;; Return a new cursor for EXPRESSIONS with OFFSETS. @@ -1526,8 +1527,6 @@ expressions; a `progn' form will be returned enclosing these forms." ;;; Matching of specs. -(defvar edebug-after-dotted-spec nil) - (defvar edebug-matching-depth 0) ;; initial value @@ -1588,36 +1587,48 @@ expressions; a `progn' form will be returned enclosing these forms." (let ((edebug-dotted-spec t));; Containing spec list was dotted. (edebug-match-specs cursor (list specs) remainder-handler))) - ;; Is the form dotted? - ((not (listp (edebug-cursor-expressions cursor)));; allow nil + ;; The reason for processing here &optional, &rest, and vectors + ;; which might contain them even when the form is dotted is to + ;; allow them to match nothing, so we can advance to the dotted + ;; part of the spec. + ((or (listp (edebug-cursor-expressions cursor)) + (vectorp (car specs)) + (memq (car specs) '(&optional &rest))) ; Process normally. + ;; (message "%scursor=%s specs=%s" + ;; (make-string edebug-matching-depth ?|) cursor (car specs)) + (let* ((spec (car specs)) + (rest) + (first-char (and (symbolp spec) (aref (symbol-name spec) 0))) + (match (cond + ((eq ?& first-char);; "&" symbols take all following specs. + (funcall (get-edebug-spec spec) cursor (cdr specs))) + ((eq ?: first-char);; ":" symbols take one following spec. + (setq rest (cdr (cdr specs))) + (funcall (get-edebug-spec spec) cursor (car (cdr specs)))) + (t;; Any other normal spec. + (setq rest (cdr specs)) + (edebug-match-one-spec cursor spec))))) + ;; The first match result may not be a list, which can happen + ;; when matching the tail of a dotted list. In that case + ;; there is no remainder. + (if (listp match) + (nconc match + (funcall remainder-handler cursor rest remainder-handler)) + match))) + + ;; Must be a dotted form, with no remaining &rest or &optional specs to + ;; match. + (t (if (not edebug-dotted-spec) (edebug-no-match cursor "Dotted spec required.")) ;; Cancel dotted spec and dotted form. (let ((edebug-dotted-spec) - (this-form (edebug-cursor-expressions cursor)) - (this-offset (edebug-cursor-offsets cursor))) - ;; Wrap the form in a list, (by changing the cursor??)... + (this-form (edebug-cursor-expressions cursor)) + (this-offset (edebug-cursor-offsets cursor))) + ;; Wrap the form in a list, by changing the cursor. (edebug-set-cursor cursor (list this-form) this-offset) - ;; and process normally, then unwrap the result. - (car (edebug-match-specs cursor specs remainder-handler)))) - - (t;; Process normally. - (let* ((spec (car specs)) - (rest) - (first-char (and (symbolp spec) (aref (symbol-name spec) 0)))) - ;;(message "spec = %s first char = %s" spec first-char) (sit-for 1) - (nconc - (cond - ((eq ?& first-char);; "&" symbols take all following specs. - (funcall (get-edebug-spec spec) cursor (cdr specs))) - ((eq ?: first-char);; ":" symbols take one following spec. - (setq rest (cdr (cdr specs))) - (funcall (get-edebug-spec spec) cursor (car (cdr specs)))) - (t;; Any other normal spec. - (setq rest (cdr specs)) - (edebug-match-one-spec cursor spec))) - (funcall remainder-handler cursor rest remainder-handler))))))) - + ;; Process normally, then unwrap the result. + (car (edebug-match-specs cursor specs remainder-handler))))))) ;; Define specs for all the symbol specs with functions used to process them. ;; Perhaps we shouldn't be doing this with edebug-form-specs since the diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index 9ff742c4331..37bcfc2003d 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -133,7 +133,7 @@ be of the form (VALUEFORM), which is evaluated and checked for nil; i.e. SYMBOL can be omitted if only the test result is of interest." (declare (indent 2) - (debug ((&rest [&or symbolp (symbolp form) (sexp)]) + (debug ((&rest [&or symbolp (symbolp form) (form)]) form body))) (if varlist `(let* ,(setq varlist (internal--build-bindings varlist)) @@ -156,7 +156,9 @@ VARLIST is the same as in `if-let*'." "Bind variables according to VARLIST and conditionally eval BODY. Like `when-let*', except if BODY is empty and all the bindings are non-nil, then the result is non-nil." - (declare (indent 1) (debug when-let*)) + (declare (indent 1) + (debug ((&rest [&or symbolp (symbolp form) (form)]) + body))) (let (res) (if varlist `(let* ,(setq varlist (internal--build-bindings varlist)) @@ -168,7 +170,7 @@ are non-nil, then the result is non-nil." "Bind variables according to SPEC and eval THEN or ELSE. Like `if-let*' except SPEC can have the form (SYMBOL VALUEFORM)." (declare (indent 2) - (debug ([&or (&rest [&or symbolp (symbolp form) (sexp)]) + (debug ([&or (&rest [&or symbolp (symbolp form) (form)]) (symbolp form)] form body)) (obsolete "use `if-let*' instead." "26.1")) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index e8d11584fab..cf2218dd1ec 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -1055,7 +1055,7 @@ Also see `tramp-file-name-structure'.") "\\(-\\|[^/|:]\\{2,\\}\\)" ;; At least one character for method. "[^/|:]+") - ":\\'") + ":") "Regular expression matching file names handled by Tramp autoload. It must match the initial `tramp-syntax' settings. It should not match file names at root of the underlying local file system, @@ -2323,8 +2323,7 @@ Falls back to normal file name handler if no Tramp file name handler exists." 'tramp-autoload-file-name-handler)) (put 'tramp-autoload-file-name-handler 'safe-magic t))) -;;;###autoload -(tramp-register-autoload-file-name-handlers) +;;;###autoload (tramp-register-autoload-file-name-handlers) (defun tramp-use-absolute-autoload-file-names () "Change Tramp autoload objects to use absolute file names. diff --git a/lisp/tree-widget.el b/lisp/tree-widget.el index 130d8af07e5..9599cc7f067 100644 --- a/lisp/tree-widget.el +++ b/lisp/tree-widget.el @@ -504,7 +504,7 @@ Handle mouse button 1 click on buttons.") (define-widget 'tree-widget-end-guide 'item "End of a vertical guide line." - :tag " `" + :tag " \\=`" ;;:tag-glyph (tree-widget-find-image "end-guide") :format "%t" ) diff --git a/src/buffer.c b/src/buffer.c index 6e3412c3d05..c6f9eb28e25 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -5620,6 +5620,8 @@ file I/O and the behavior of various editing commands. This variable is buffer-local but you cannot set it directly; use the function `set-buffer-multibyte' to change a buffer's representation. +To prevent any attempts to set it or make it buffer-local, Emacs will +signal an error in those cases. See also Info node `(elisp)Text Representations'. */); make_symbol_constant (intern_c_string ("enable-multibyte-characters")); diff --git a/src/bytecode.c b/src/bytecode.c index ebaf3c3a7fc..8746568f166 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -1346,10 +1346,8 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, /* Actually this is Bstack_ref with offset 0, but we use Bdup for that instead. */ /* CASE (Bstack_ref): */ - call3 (Qerror, - build_string ("Invalid byte opcode: op=%s, ptr=%d"), - make_number (op), - make_number (pc - 1 - bytestr_data)); + error ("Invalid byte opcode: op=%d, ptr=%"pD"d", + op, pc - 1 - bytestr_data); /* Handy byte-codes for lexical binding. */ CASE (Bstack_ref1): diff --git a/src/data.c b/src/data.c index 7ca1892f64a..3c9152049b7 100644 --- a/src/data.c +++ b/src/data.c @@ -3896,12 +3896,14 @@ syms_of_data (void) set_symbol_function (Qwholenump, XSYMBOL (Qnatnump)->u.s.function); DEFVAR_LISP ("most-positive-fixnum", Vmost_positive_fixnum, - doc: /* The largest value that is representable in a Lisp integer. */); + doc: /* The largest value that is representable in a Lisp integer. +This variable cannot be set; trying to do so will signal an error. */); Vmost_positive_fixnum = make_number (MOST_POSITIVE_FIXNUM); make_symbol_constant (intern_c_string ("most-positive-fixnum")); DEFVAR_LISP ("most-negative-fixnum", Vmost_negative_fixnum, - doc: /* The smallest value that is representable in a Lisp integer. */); + doc: /* The smallest value that is representable in a Lisp integer. +This variable cannot be set; trying to do so will signal an error. */); Vmost_negative_fixnum = make_number (MOST_NEGATIVE_FIXNUM); make_symbol_constant (intern_c_string ("most-negative-fixnum")); diff --git a/src/font.c b/src/font.c index 51625b49fa8..f7cebdce78c 100644 --- a/src/font.c +++ b/src/font.c @@ -5421,19 +5421,22 @@ gets the repertory information by an opened font and ENCODING. */); doc: /* Vector of valid font weight values. Each element has the form: [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...] -NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */); +NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. +This variable cannot be set; trying to do so will signal an error. */); Vfont_weight_table = BUILD_STYLE_TABLE (weight_table); make_symbol_constant (intern_c_string ("font-weight-table")); DEFVAR_LISP_NOPRO ("font-slant-table", Vfont_slant_table, doc: /* Vector of font slant symbols vs the corresponding numeric values. -See `font-weight-table' for the format of the vector. */); +See `font-weight-table' for the format of the vector. +This variable cannot be set; trying to do so will signal an error. */); Vfont_slant_table = BUILD_STYLE_TABLE (slant_table); make_symbol_constant (intern_c_string ("font-slant-table")); DEFVAR_LISP_NOPRO ("font-width-table", Vfont_width_table, doc: /* Alist of font width symbols vs the corresponding numeric values. -See `font-weight-table' for the format of the vector. */); +See `font-weight-table' for the format of the vector. +This variable cannot be set; trying to do so will signal an error. */); Vfont_width_table = BUILD_STYLE_TABLE (width_table); make_symbol_constant (intern_c_string ("font-width-table")); diff --git a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el index f52a2b1896c..ca49dcd213d 100644 --- a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el +++ b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el @@ -126,5 +126,9 @@ !start!(with-current-buffer (get-buffer-create "*edebug-test-code-buffer*") !body!(format "current-buffer: %s" (current-buffer)))) +(defun edebug-test-code-use-destructuring-bind () + (let ((two 2) (three 3)) + (cl-destructuring-bind (x . y) (cons two three) (+ x!x! y!y!)))) + (provide 'edebug-test-code) ;;; edebug-test-code.el ends here diff --git a/test/lisp/emacs-lisp/edebug-tests.el b/test/lisp/emacs-lisp/edebug-tests.el index 02f4d1c5abe..f6c016cdf80 100644 --- a/test/lisp/emacs-lisp/edebug-tests.el +++ b/test/lisp/emacs-lisp/edebug-tests.el @@ -899,5 +899,19 @@ test and possibly others should be updated." "@g" (should (equal edebug-tests-@-result '(#("abcd" 1 3 (face italic)) 511)))))) +(ert-deftest edebug-tests-dotted-forms () + "Edebug can instrument code matching the tail of a dotted spec (Bug#6415)." + (edebug-tests-with-normal-env + (edebug-tests-setup-@ "use-destructuring-bind" nil t) + (edebug-tests-run-kbd-macro + "@ SPC SPC SPC SPC SPC SPC" + (edebug-tests-should-be-at "use-destructuring-bind" "x") + (edebug-tests-should-match-result-in-messages "2 (#o2, #x2, ?\\C-b)") + "SPC" + (edebug-tests-should-be-at "use-destructuring-bind" "y") + (edebug-tests-should-match-result-in-messages "3 (#o3, #x3, ?\\C-c)") + "g" + (should (equal edebug-tests-@-result 5))))) + (provide 'edebug-tests) ;;; edebug-tests.el ends here diff --git a/test/lisp/emacs-lisp/subr-x-tests.el b/test/lisp/emacs-lisp/subr-x-tests.el index 0e8871d9a9c..0187f39d15d 100644 --- a/test/lisp/emacs-lisp/subr-x-tests.el +++ b/test/lisp/emacs-lisp/subr-x-tests.el @@ -403,7 +403,7 @@ (should-error (eval '(and-let* (nil (x 1))) lexical-binding) :type 'setting-constant) (should (equal nil (and-let* ((nil) (x 1))))) - (should-error (eval (and-let* (2 (x 1))) lexical-binding) + (should-error (eval '(and-let* (2 (x 1))) lexical-binding) :type 'wrong-type-argument) (should (equal 1 (and-let* ((2) (x 1))))) (should (equal 2 (and-let* ((x 1) (2))))) diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index efc2c578d59..8310003d9b1 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -3627,11 +3627,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (skip-unless (tramp--test-enabled)) ;; We test it only for the mock-up connection; otherwise there might ;; be problems with the used ports. - (skip-unless - (and - (eq tramp-syntax 'default) - (string-equal - "mock" (file-remote-p tramp-test-temporary-file-directory 'method)))) + (skip-unless (and (eq tramp-syntax 'default) + (tramp--test-mock-p))) ;; We force a reconnect, in order to have a clean environment. (dolist (dir `(,tramp-test-temporary-file-directory @@ -4041,6 +4038,12 @@ Several special characters do not work properly there." (file-truename tramp-test-temporary-file-directory) nil (string-match "^HP-UX" (tramp-get-connection-property v "uname" "")))) +(defun tramp--test-mock-p () + "Check, whether the mock method is used. +This does not support external Emacs calls." + (string-equal + "mock" (file-remote-p tramp-test-temporary-file-directory 'method))) + (defun tramp--test-rsync-p () "Check, whether the rsync method is used. This does not support special file names." @@ -4496,8 +4499,7 @@ process sentinels. They shall not disturb each other." ;; We must distinguish due to performance reasons. (timer-operation (cond - ((string-equal "mock" (file-remote-p tmp-name 'method)) - 'vc-registered) + ((tramp--test-mock-p) 'vc-registered) (t 'file-attributes))) timer buffers kill-buffer-query-functions) @@ -4615,7 +4617,27 @@ process sentinels. They shall not disturb each other." (ignore-errors (cancel-timer timer)) (ignore-errors (delete-directory tmp-name 'recursive))))))) -(ert-deftest tramp-test42-recursive-load () +(ert-deftest tramp-test42-auto-load () + "Check that Tramp autoloads properly." + (skip-unless (tramp--test-enabled)) + (skip-unless (not (tramp--test-mock-p))) + + (let ((default-directory (expand-file-name temporary-file-directory))) + (let ((code + (format + "(message \"Tramp loaded: %%s\" (consp (file-attributes \"%s\")))" + tramp-test-temporary-file-directory))) + (should + (string-match + "Tramp loaded: t[\n\r]+" + (shell-command-to-string + (format + "%s -batch -Q -L %s --eval %s" + (expand-file-name invocation-name invocation-directory) + (mapconcat 'shell-quote-argument load-path " -L ") + (shell-quote-argument code)))))))) + +(ert-deftest tramp-test43-recursive-load () "Check that Tramp does not fail due to recursive load." (skip-unless (tramp--test-enabled)) @@ -4638,7 +4660,7 @@ process sentinels. They shall not disturb each other." (mapconcat 'shell-quote-argument load-path " -L ") (shell-quote-argument code)))))))) -(ert-deftest tramp-test43-remote-load-path () +(ert-deftest tramp-test44-remote-load-path () "Check that Tramp autoloads its packages with remote `load-path'." ;; `tramp-cleanup-all-connections' is autoloaded from tramp-cmds.el. ;; It shall still work, when a remote file name is in the @@ -4661,7 +4683,7 @@ process sentinels. They shall not disturb each other." (mapconcat 'shell-quote-argument load-path " -L ") (shell-quote-argument code))))))) -(ert-deftest tramp-test44-delay-load () +(ert-deftest tramp-test45-delay-load () "Check that Tramp is loaded lazily, only when needed." ;; Tramp is neither loaded at Emacs startup, nor when completing a ;; non-Tramp file name like "/foo". Completing a Tramp-alike file @@ -4688,7 +4710,7 @@ process sentinels. They shall not disturb each other." (mapconcat 'shell-quote-argument load-path " -L ") (shell-quote-argument (format code tm))))))))) -(ert-deftest tramp-test45-unload () +(ert-deftest tramp-test46-unload () "Check that Tramp and its subpackages unload completely. Since it unloads Tramp, it shall be the last test to run." :tags '(:expensive-test) |