On Wed, Jul 13, 2022 at 11:40 PM Robert P. Goldman <rpgoldman@sift.net> wrote:
Given that structure accessors can be open coded you need a solution that can force recompilation. You could get that with a build system like asdf. You’d have to remember to rebuild the system instead of just recompiling the defstruct form, but that would work

Thanks. Yes. I use asdf and was thinking that if I do get into the losing situation I would just do a forced reload of my system. It needs to be forced because the files that need to be recompiled haven't necessarily changed.

Alan
 

-- 
Robert P. Goldman

On July 13, 2022 at 20:40:33, Ville Voutilainen (ville.voutilainen@gmail.com) wrote:

On Thu, 14 Jul 2022 at 00:50, Alan Ruttenberg <alanruttenberg@gmail.com> wrote:

This is what I came up with:

https://github.com/alanruttenberg/abcl/commit/a9c5541d372012d24c0daa704a22fc637398e086

Depending on the value of switch switch sys::*allow-defstruct-redefinition*. In order to allow the structure to be redefined, we delete the structure class, if there is already one.

The undefined behavior is now
1. use of an existing struct from before the redefinition.
2. creation of functions with the same name as a structure element that has been removed.
3. running existing compiled code that uses an accessor for a slot that has changed relative position in the structure.


#2 can be fixed by removing the source transformation for the accessor.
(sys::%set-function-info accessor nil). It's not hard - involves iterating through the accessors just before the defstruct is redefined.
I don't think I'm going to bother fixing this at the moment.

#3 can be avoided by (declare (notinline accessor)) in the function being defined. Arguably this is what should be done if (declare (optimize (debug 3))).
I could also have sys::not-inline-p return true if debug is 3. I may try to do this, since it will be easy to forget to recompile.
We could at least provide warnings for such functions if we recorded that the source transform was applied, during compilation

BTW, if you have an existing (regular) class and create a defstruct with the same name, it blows away the previous class.
That probably deserves a warning.

Comments welcome.

Greetings from the (for the two decades of it) other side of the
fence, where compilations and one-definition-rules
are rather more static than here. :)

Sure, this looks plausible, and it probably works in many cases. But
if you COMPILE something with one definition
of a defstruct, then defstruct again, what happens if you try to call
the thing you compiled before?

I don't claim to claim it "can't work". But I have a vague
understanding why there might be a reason for "this might not work".
:P

As an unsubstantiated rumination, it might be *more* difficult to make
this work in a language that can do dynamic compilation
at any point in a program than it is in a language that is more static
as far as struct definitions and their compilations are concerned.
My architecture-brain can't tell how you could possibly know where all
the 'references' to the old defstruct could possibly be,
considering that compilations with the old one and uses of those can
be so dynamic, and where the uses that would expect
the newer redefinitions might be, and how you'd track that.

Again, I'm not saying this can't work. I just find it daunting to even
ponder what sort of funny situations where your program
manages to confuse itself about which struct is which you can end up
with. Maybe that's a theoretical problem, but it hurts my brain. :D