aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2023-09-04 12:51:24 +0000
committerAlan Mackenzie2023-09-04 12:51:24 +0000
commitafcb6d0bc7abcdbca6b18d020deeff24d1ad197f (patch)
tree1561281df0284ced50d19005770c00023e7a617e
parent55a0f0e047034b3a458b6fdbe245f33b83fd88b0 (diff)
downloademacs-afcb6d0bc7abcdbca6b18d020deeff24d1ad197f.tar.gz
emacs-afcb6d0bc7abcdbca6b18d020deeff24d1ad197f.zip
Correct the handling of symbols with position in equal
* src/fns.c (internal_equal): Only regard symbols with position as their symbols when symbols-with-pos-enabled is non-nil. * doc/lispref/symbols.texi (Symbols with Position): Expand the description of symbols with position, in particular the way they work with eq and equal. * doc/lispref/objects.texi (Equality Predicates): Describe how eq and equal handle symbols with position. * test/src/fns-tests.el (fns-tests-equal-symbols-with-position): New tests for symbols with position.
-rw-r--r--doc/lispref/objects.texi11
-rw-r--r--doc/lispref/symbols.texi40
-rw-r--r--src/fns.c20
-rw-r--r--test/src/fns-tests.el20
4 files changed, 72 insertions, 19 deletions
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index ad079e0d63a..784d59720ed 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -2206,6 +2206,10 @@ and the same non-fixnum numeric type, then they might or might not be
2206the same object, and @code{eq} returns @code{t} or @code{nil} 2206the same object, and @code{eq} returns @code{t} or @code{nil}
2207depending on whether the Lisp interpreter created one object or two. 2207depending on whether the Lisp interpreter created one object or two.
2208 2208
2209If @var{object1} or @var{object2} is a symbol with position, @code{eq}
2210regards it as its bare symbol when @code{symbols-with-pos-enabled} is
2211non-@code{nil} (@pxref{Symbols with Position}).
2212
2209@example 2213@example
2210@group 2214@group
2211(eq 'foo 'foo) 2215(eq 'foo 'foo)
@@ -2363,6 +2367,13 @@ same sequence of character codes and all these codes are in the range
2363The @code{equal} function recursively compares the contents of objects 2367The @code{equal} function recursively compares the contents of objects
2364if they are integers, strings, markers, vectors, bool-vectors, 2368if they are integers, strings, markers, vectors, bool-vectors,
2365byte-code function objects, char-tables, records, or font objects. 2369byte-code function objects, char-tables, records, or font objects.
2370
2371If @var{object1} or @var{object2} is a symbol with position,
2372@code{equal} regards it as its bare symbol when
2373@code{symbols-with-pos-enabled} is non-@code{nil}. Otherwise
2374@code{equal} compares two symbols with position by recursively
2375comparing their components. @xref{Symbols with Position}.
2376
2366Other objects are considered @code{equal} only if they are @code{eq}. 2377Other objects are considered @code{equal} only if they are @code{eq}.
2367For example, two distinct buffers are never considered @code{equal}, 2378For example, two distinct buffers are never considered @code{equal},
2368even if their textual contents are the same. 2379even if their textual contents are the same.
diff --git a/doc/lispref/symbols.texi b/doc/lispref/symbols.texi
index 34db0caf3a8..1f3b677d7fb 100644
--- a/doc/lispref/symbols.texi
+++ b/doc/lispref/symbols.texi
@@ -783,10 +783,15 @@ Symbol forms whose names start with @samp{#_} are not transformed.
783 783
784@cindex bare symbol 784@cindex bare symbol
785A @dfn{symbol with position} is a symbol, the @dfn{bare symbol}, 785A @dfn{symbol with position} is a symbol, the @dfn{bare symbol},
786together with an unsigned integer called the @dfn{position}. These 786together with an unsigned integer called the @dfn{position}. Symbols
787objects are intended for use by the byte compiler, which records in 787with position don't themselves have entries in the obarray (though
788them the position of each symbol occurrence and uses those positions 788their bare symbols do; @pxref{Creating Symbols}).
789in warning and error messages. 789
790Symbols with position are for the use of the byte compiler, which
791records in them the position of each symbol occurrence and uses those
792positions in warning and error messages. They shouldn't normally be
793used otherwise. Doing so can cause unexpected results with basic
794Emacs functions such as @code{eq} and @code{equal}.
790 795
791The printed representation of a symbol with position uses the hash 796The printed representation of a symbol with position uses the hash
792notation outlined in @ref{Printed Representation}. It looks like 797notation outlined in @ref{Printed Representation}. It looks like
@@ -798,11 +803,20 @@ the compiled Lisp file.
798 803
799For most purposes, when the flag variable 804For most purposes, when the flag variable
800@code{symbols-with-pos-enabled} is non-@code{nil}, symbols with 805@code{symbols-with-pos-enabled} is non-@code{nil}, symbols with
801positions behave just as bare symbols do. For example, @samp{(eq 806positions behave just as their bare symbols would. For example,
802#<symbol foo at 12345> foo)} has a value @code{t} when that variable 807@samp{(eq #<symbol foo at 12345> foo)} has a value @code{t} when the
803is set (but @code{nil} when it isn't set). Most of the time in Emacs this 808variable is set; likewise, @code{equal} will treat a symbol with
804variable is @code{nil}, but the byte compiler binds it to @code{t} 809position argument as its bare symbol.
805when it runs. 810
811When @code{symbols-with-pos-enabled} is @code{nil}, any symbols with
812position continue to exist, but do not behave as symbols, or have the
813other useful properties outlined in the previous paragraph. @code{eq}
814returns @code{t} when given identical arguments, and @code{equal}
815returns @code{t} when given arguments with @code{equal} components.
816
817Most of the time in Emacs @code{symbols-with-pos-enabled} is
818@code{nil}, but the byte compiler and the native compiler bind it to
819@code{t} when they run.
806 820
807Typically, symbols with position are created by the byte compiler 821Typically, symbols with position are created by the byte compiler
808calling the reader function @code{read-positioning-symbols} 822calling the reader function @code{read-positioning-symbols}
@@ -810,17 +824,17 @@ calling the reader function @code{read-positioning-symbols}
810@code{position-symbol}. 824@code{position-symbol}.
811 825
812@defvar symbols-with-pos-enabled 826@defvar symbols-with-pos-enabled
813When this variable is non-@code{nil}, symbols with position behave 827When this variable is non-@code{nil}, a symbol with position behaves
814like the contained bare symbol. Emacs runs a little more slowly in 828like the contained bare symbol. Emacs runs a little more slowly in
815this case. 829this case.
816@end defvar 830@end defvar
817 831
818@defvar print-symbols-bare 832@defvar print-symbols-bare
819When bound to non-@code{nil}, the Lisp printer prints only the bare symbol of 833When bound to non-@code{nil}, the Lisp printer prints only the bare
820a symbol with position, ignoring the position. 834symbol of a symbol with position, ignoring the position.
821@end defvar 835@end defvar
822 836
823@defun symbol-with-pos-p symbol. 837@defun symbol-with-pos-p symbol
824This function returns @code{t} if @var{symbol} is a symbol with 838This function returns @code{t} if @var{symbol} is a symbol with
825position, @code{nil} otherwise. 839position, @code{nil} otherwise.
826@end defun 840@end defun
diff --git a/src/fns.c b/src/fns.c
index ae9969a5432..bd1d63a58c4 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2774,10 +2774,13 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
2774 2774
2775 /* A symbol with position compares the contained symbol, and is 2775 /* A symbol with position compares the contained symbol, and is
2776 `equal' to the corresponding ordinary symbol. */ 2776 `equal' to the corresponding ordinary symbol. */
2777 if (SYMBOL_WITH_POS_P (o1)) 2777 if (symbols_with_pos_enabled)
2778 o1 = SYMBOL_WITH_POS_SYM (o1); 2778 {
2779 if (SYMBOL_WITH_POS_P (o2)) 2779 if (SYMBOL_WITH_POS_P (o1))
2780 o2 = SYMBOL_WITH_POS_SYM (o2); 2780 o1 = SYMBOL_WITH_POS_SYM (o1);
2781 if (SYMBOL_WITH_POS_P (o2))
2782 o2 = SYMBOL_WITH_POS_SYM (o2);
2783 }
2781 2784
2782 if (BASE_EQ (o1, o2)) 2785 if (BASE_EQ (o1, o2))
2783 return true; 2786 return true;
@@ -2825,8 +2828,8 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
2825 if (ASIZE (o2) != size) 2828 if (ASIZE (o2) != size)
2826 return false; 2829 return false;
2827 2830
2828 /* Compare bignums, overlays, markers, and boolvectors 2831 /* Compare bignums, overlays, markers, boolvectors, and
2829 specially, by comparing their values. */ 2832 symbols with position specially, by comparing their values. */
2830 if (BIGNUMP (o1)) 2833 if (BIGNUMP (o1))
2831 return mpz_cmp (*xbignum_val (o1), *xbignum_val (o2)) == 0; 2834 return mpz_cmp (*xbignum_val (o1), *xbignum_val (o2)) == 0;
2832 if (OVERLAYP (o1)) 2835 if (OVERLAYP (o1))
@@ -2858,6 +2861,11 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
2858 if (TS_NODEP (o1)) 2861 if (TS_NODEP (o1))
2859 return treesit_node_eq (o1, o2); 2862 return treesit_node_eq (o1, o2);
2860#endif 2863#endif
2864 if (SYMBOL_WITH_POS_P(o1)) /* symbols_with_pos_enabled is false. */
2865 return (BASE_EQ (XSYMBOL_WITH_POS (o1)->sym,
2866 XSYMBOL_WITH_POS (o2)->sym)
2867 && BASE_EQ (XSYMBOL_WITH_POS (o1)->pos,
2868 XSYMBOL_WITH_POS (o2)->pos));
2861 2869
2862 /* Aside from them, only true vectors, char-tables, compiled 2870 /* Aside from them, only true vectors, char-tables, compiled
2863 functions, and fonts (font-spec, font-entity, font-object) 2871 functions, and fonts (font-spec, font-entity, font-object)
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el
index 79ae4393f40..9c09e4f0c33 100644
--- a/test/src/fns-tests.el
+++ b/test/src/fns-tests.el
@@ -98,6 +98,26 @@
98 (should-not (equal-including-properties #("a" 0 1 (k "v")) 98 (should-not (equal-including-properties #("a" 0 1 (k "v"))
99 #("b" 0 1 (k "v"))))) 99 #("b" 0 1 (k "v")))))
100 100
101(ert-deftest fns-tests-equal-symbols-with-position ()
102 "Test `eq' and `equal' on symbols with position."
103 (let ((foo1 (position-symbol 'foo 42))
104 (foo2 (position-symbol 'foo 666))
105 (foo3 (position-symbol 'foo 42)))
106 (let (symbols-with-pos-enabled)
107 (should (eq foo1 foo1))
108 (should (equal foo1 foo1))
109 (should-not (eq foo1 foo2))
110 (should-not (equal foo1 foo2))
111 (should-not (eq foo1 foo3))
112 (should (equal foo1 foo3)))
113 (let ((symbols-with-pos-enabled t))
114 (should (eq foo1 foo1))
115 (should (equal foo1 foo1))
116 (should (eq foo1 foo2))
117 (should (equal foo1 foo2))
118 (should (eq foo1 foo3))
119 (should (equal foo1 foo3)))))
120
101(ert-deftest fns-tests-reverse () 121(ert-deftest fns-tests-reverse ()
102 (should-error (reverse)) 122 (should-error (reverse))
103 (should-error (reverse 1)) 123 (should-error (reverse 1))