Subject: bug#40671: [DOC] modify literal objects

From: Dmitry Gutov <[email-masked]>
Date: Mon, 27 Apr 2020 03:53:51 +0300

On 27.04.2020 02:13, Paul Eggert wrote:

>> This just illustrates a weakness of type system in C/C++. The same way you could
>> pass a string into a function that expects an int.
> 
> Although it's a weakness, it's different from the char * vs int weakness. It's
> well-defined in C that one can cast char * to char const * and back without
> trouble. The same is not true for casting char * to int and back.

This compiles fine:

   #include <string.h>
   int main (void) { return !strcpy ((char*)2, "b"); }

My point is, it's hard to discuss static typing guarantees when type 
casting is involved.

>> is it undefined?
> 
> Yes, it's undefined. C11 section 6.7.3 paragraph 6 says, "If an attempt is made
> to modify an object defined with a const-qualified type through use of an lvalue
> with non-const-qualified type, the behavior is undefined."

Sorry if that was unclear. I mean, is the behavior of "literal objects" 
in Emacs Lisp undefined when one tries to modify them?

>> Do you have an example of a version of Emacs where this behavior was different?
> 
> Emacs 26.

Sorry, I don't have an Emacs 26 at hand. Should 25 suffice? Just tried 
this in IELM:

ELISP> (setq a '(1 . 2))
(1 . 2)

ELISP> (setcdr a 3)
3 (#o3, #x3, ?\C-c)
ELISP> a
(1 . 3)

ELISP> emacs-version
"25.2.3"

>>> Unfortunately, the relevant code is hairy and any fixes certainly won't happen
>>> before the Emacs 27 release. In the meantime it's better to warn users clearly
>>> about the gotchas in this area, to help prevent some of the confusion
>>> exemplified by Bug#40671.
>>
>> Perhaps you meant some other bug report?
> 
> No, the original bug report that started this thread illustrates some of the
> confusion in this area.

Okay, yes. I though you had a bug report with a description of a 
practical problem.

>> In all of my experience, the term "constant" is usually applied to names
>> (variables), or pointers. And it almost always means that you're not allowed to
>> change it. Or if you are, you can't do it by accident.
> 
> Unfortunately that experience does not apply to C and to other low-level
> languages. Even Java once allowed programs to modify "constants" by using
> reflection, though recent Java versions have fixed this.

Hence the last sentence of my paragraph you quoted.

In Ruby, we also have "constants" and we sometimes laugh about being 
able to change them. And yet, there also you can't do it by accident.

>> The previous term "literal objects", however, seems accurate enough
> 
> We could use any term we like, and if there's consensus for using the term
> "literal object" instead of "constant" then we can redo the manual that way.
> However, the problem can occur with strings that were never string literals in
> any source-code Elisp program. And a Elisp string can begin its life as a
> mutable string and then become a "constant" (or "literal object") later. So it's
> not clear that the longer phrase is less confusing.

"A mutable string can become a constant later and yet remain modifiable 
in practice" sounds really confusing.

We better warn against modifying any values that are part of a "literal 
object" anywhere.