From fdb4519ca621fbfd893f23f62ef0b97379f9c8a9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= <mattiase@acm.org>
Date: Wed, 1 Jan 2020 13:06:39 +0100
Subject: [PATCH] Clarify 'eq' on numbers

* doc/lispref/numbers.texi (Integer Basics):
* doc/lispref/objects.texi (Integer Type, Equality Predicates):
* etc/NEWS:

Recommend that 'eq' not be used to compare numbers, and fix some
erroneous or misleading examples.  See discussion starting at
https://lists.gnu.org/archive/html/emacs-devel/2019-12/msg00856.html
and bug#38708.
---
 doc/lispref/numbers.texi |  2 ++
 doc/lispref/objects.texi | 32 +++++++++++++++++---------------
 etc/NEWS                 |  3 ++-
 3 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi
index e952980f26..1c6f8ae7be 100644
--- a/doc/lispref/numbers.texi
+++ b/doc/lispref/numbers.texi
@@ -41,6 +41,8 @@ Integer Basics
 Some functions in Emacs accept only fixnums.  Also, while fixnums can
 always be compared for numeric equality with @code{eq}, bignums
 require more-heavyweight equality predicates like @code{eql}.
+To avoid any concern about fixnum ranges, use @code{eql} or @code{=}
+for comparing numbers.
 
   The range of values for bignums is limited by the amount of main
 memory, by machine characteristics such as the size of the word used
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 4be2eb6918..a0ce7aebd0 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -270,7 +270,9 @@ Integer Type
 @code{eql} or @code{=}.  To test whether an integer is a fixnum or a
 bignum, you can compare it to @code{most-negative-fixnum} and
 @code{most-positive-fixnum}, or you can use the convenience predicates
-@code{fixnump} and @code{bignump} on any object.
+@code{fixnump} and @code{bignump} on any object.  Most of the time,
+however, it is more convenient to ignore the difference and use
+@code{eql} or @code{=} for comparing any kind of number.
 
   The read syntax for integers is a sequence of (base ten) digits with an
 optional sign at the beginning and an optional period at the end.  The
@@ -2167,19 +2169,20 @@ Equality Predicates
 This function returns @code{t} if @var{object1} and @var{object2} are
 the same object, and @code{nil} otherwise.
 
-If @var{object1} and @var{object2} are fixnums with the same value,
-they are considered to be the same object (i.e., @code{eq} returns
-@code{t}).  If @var{object1} and @var{object2} are symbols with the
+Numbers in general do not have an object identity and therefore cannot
+be compared reliably using @code{eq}.  While fixnums (and characters)
+with the same value are considered to be the same object (i.e.,
+@code{eq} returns @code{t}), this is not true for bignums and floats.
+For maximum portability and robustness, avoid using @code{eq} for
+numbers (@pxref{Comparison of Numbers}).
+
+If @var{object1} and @var{object2} are symbols with the
 same name, they are normally the same object---but see @ref{Creating
 Symbols} for exceptions.  For other types (e.g., lists, vectors,
 strings), two arguments with the same contents or elements are not
 necessarily @code{eq} to each other: they are @code{eq} only if they
 are the same object, meaning that a change in the contents of one will
 be reflected by the same change in the contents of the other.
-For other types of objects whose contents cannot be changed (e.g.,
-bignums and floats), two arguments with the same contents might or might not be
-the same object, and @code{eq} returns @code{t} or @code{nil}
-depending on whether the Lisp interpreter created one object or two.
 
 @example
 @group
@@ -2188,26 +2191,25 @@ Equality Predicates
 @end group
 
 @group
-(eq 456 456)
+(eq ?A ?A)
      @result{} t
 @end group
 
 @group
 (eq 3.0 3.0)
      @result{} t @r{or} nil
-;; @r{The result is implementation-dependent.}
+;; @r{Equal floats may or may not be the same object.}
 @end group
 
 @group
-(eq "asdf" "asdf")
+(eq (make-string 3 ?A) (make-string 3 ?A))
      @result{} nil
 @end group
 
 @group
-(eq "" "")
-     @result{} t
-;; @r{This exception occurs because Emacs Lisp}
-;; @r{makes just one multibyte empty string, to save space.}
+(eq "asdf" "asdf")
+     @result{} t @r{or} nil
+;; @r{Equal string constants may or may not be the same object.}
 @end group
 
 @group
diff --git a/etc/NEWS b/etc/NEWS
index a8c8e2763e..efcd63e35c 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2879,7 +2879,8 @@ All the arithmetic, comparison, and logical (a.k.a. "bitwise")
 operations where bignums make sense now support both fixnums and
 bignums.  However, note that unlike fixnums, bignums will not compare
 equal with 'eq', you must use 'eql' instead.  (Numerical comparison
-with '=' works on both, of course.)
+with '=' works on both, of course.)  To avoid mistakes, we recommend
+that you do not use 'eq' for comparing numbers at all.
 
 Since large bignums consume a lot of memory, Emacs limits the size of
 the largest bignum a Lisp program is allowed to create.  The
-- 
2.21.0 (Apple Git-122.2)

