diff options
author | Mattias EngdegÄrd <mattiase@acm.org> | 2024-03-06 12:03:06 +0100 |
---|---|---|
committer | Mattias EngdegÄrd <mattiase@acm.org> | 2024-03-07 13:47:53 +0100 |
commit | 61b2f5f96b1d9dfd2fd908e09fac0d4163049c42 (patch) | |
tree | e76095045e99141e287be64920502e053de5a787 | |
parent | 8aabd835747297818d538cc16b3f53fcc1dd67f6 (diff) | |
download | emacs-61b2f5f96b1d9dfd2fd908e09fac0d4163049c42.tar.gz |
Single string literal in body is return value only, not doc string
A function or macro body consisting of a single string literal now only
uses it as a return value. Previously, it had the dual uses as return
value and doc string, which was never what the programmer wanted and
had some inconvenient consequences (bug#69387).
This change applies to `lambda`, `defun`, `defsubst` and `defmacro`
forms; most other defining forms already worked in the sensible way.
* lisp/emacs-lisp/bytecomp.el (byte-compile-lambda):
Don't use a lone string literal as doc string.
* test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el
(foo): Update docstring warning test.
* doc/lispref/functions.texi (Function Documentation): Update.
* etc/NEWS: Announce.
-rw-r--r-- | doc/lispref/functions.texi | 13 | ||||
-rw-r--r-- | etc/NEWS | 16 | ||||
-rw-r--r-- | lisp/emacs-lisp/bytecomp.el | 9 | ||||
-rw-r--r-- | test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el | 3 |
4 files changed, 28 insertions, 13 deletions
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi index 344b3ff3a50..ff635fc54b2 100644 --- a/doc/lispref/functions.texi +++ b/doc/lispref/functions.texi @@ -498,13 +498,12 @@ indentation of the following lines is inside the string; what looks nice in the source code will look ugly when displayed by the help commands. - You may wonder how the documentation string could be optional, since -there are required components of the function that follow it (the body). -Since evaluation of a string returns that string, without any side effects, -it has no effect if it is not the last form in the body. Thus, in -practice, there is no confusion between the first form of the body and the -documentation string; if the only body form is a string then it serves both -as the return value and as the documentation. + A documentation string must always be followed by at least one Lisp +expression; otherwise, it is not a documentation string at all but the +single expression of the body and used as the return value. +When there is no meaningful value to return from a function, it is +standard practice to return @code{nil} by adding it after the +documentation string. The last line of the documentation string can specify calling conventions different from the actual function arguments. Write @@ -1818,6 +1818,22 @@ Tree-sitter conditionally sets 'forward-sexp-function' for major modes that have defined 'sexp' in 'treesit-thing-settings' to enable sexp-related motion commands. ++++ +** Returned strings are never docstrings. +Functions and macros whose bodies consist of a single string literal now +only return that string; it is not used as a docstring. Example: + + (defun sing-a-song () + "Sing a song.") + +The above function returns the string '"Sing a song."' but has no +docstring. Previously, that string was used as both a docstring and +return value, which was never what the programmer wanted. If you want +the string to be a docstring, add an explicit return value. + +This change applies to 'defun', 'defsubst', 'defmacro' and 'lambda' +forms; other defining forms such as 'cl-defun' already worked this way. + ** New or changed byte-compilation warnings --- diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index c3355eedd75..cf0e6d600dd 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -3061,12 +3061,11 @@ lambda-expression." (append (if (not lexical-binding) arglistvars) byte-compile-bound-variables)) (body (cdr (cdr fun))) - (doc (if (stringp (car body)) + ;; Treat a final string literal as a value, not a doc string. + (doc (if (and (cdr body) (stringp (car body))) (prog1 (car body) - ;; Discard the doc string from the body - ;; unless it is the last element of the body. - (if (cdr body) - (setq body (cdr body)))))) + ;; Discard the doc string from the body. + (setq body (cdr body))))) (int (assq 'interactive body)) command-modes) (when lexical-binding diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el index 94b0e80c979..571f7f6f095 100644 --- a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el +++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el @@ -1,3 +1,4 @@ ;;; -*- lexical-binding: t -*- (defun foo () - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + nil) |