Restore instances to their previous state on failed U-I-F-{R,D}-C
Would you welcome a patch that adds the functionality from https://github.com/sbcl/sbcl/commit/9dcaef6100feae2f99b8b524d2ee702789eaf38f into ECL? The commit message and tests should be the most interesting parts for you.
Commit message, copied over for posterity:
Neither the standard nor the MOP specify what happens when an error is
signaled in U-I-F-R-C or U-I-F-D-C and control is transferred outside.
This may result in half-baked instances which, respectively, already
have their structure or class changed, but whose newly added slots are
not yet initialized. There is no good way to "fix" the instances afterwards
since, for all purposes, SBCL considers them to be "updated" even though
their slot values are undefined.
This commit modifies the existing behavior in functions
%OBSOLETE-INSTANCE-TRAP and %CHANGE-CLASS by effectively rolling back
the transaction of updating an instance or changing its class if
U-I-F-{R,D}-C does not exit normally but via a nonlocal exit.
The new behavior is actually useful because the programmer can fix
their U-I-F-{R,D}-C code up and either attempt to access the instance
again (to trigger the update process) or call CHANGE-CLASS on it again.
Tests:
It seems that the change could be done in https://gitlab.com/embeddable-common-lisp/ecl/-/blob/4da8ca54b60e373cf8f344601e19daabbac25437/src/clos/change.lsp#L148-180 by saving the old instance stamp and contents, and then adding an UNWIND-PROTECT
form, which, in case of a non-local exit, could restore the old state of the instance.
(Edit: I would like to add a tag "feature" to this issue, but I don't seem to have the permission to do that.)
Edited by Michał "phoe" Herda