Hi Ralf,

Sorry for the late response. I've been really busy improving some other parts of ABCL which consumed all my time.
This slot accessor is not to be generated again for "c", of course, as you said. The strange thing this is that, in principle, foo-s1 is not applicable to instances of "a", but to instances of "b" and "c" only. Since new sub-structures of "a" (with conc-name foo-) can be defined at any time, the type for the applicable structures used in the implementation of foo-s1 cannot be statically encoded but must be dynamically determined, or the code for foo-s1 could be dynamically adapted for every new sub-defstruct of "a" with conc-name foo-. I tend to believe this is not easy to implement.

Actually, it's really easy to implement.

I am afraid, using defmethod for the non-optimized case is not that easy because not all defstructs are necessarily compiled with the same optimization settings (e.g., they might be located in different files). In addition, one has to remove methods if a defstruct is recompiled with other slots or with different optimization settings..... :-(

The part about the accessors being defined in different files with different optimization strategies: that's correct. However, it's not the context of the definer, but the context of the user which causes the optimized or non-optimized code path to be used.

With respect to recompilation/redefinition of a defstruct: the spec says you can't do that, or at least, you can't portably depend on that ("The consequences of redefining a defstruct structure are undefined."). ABCL allows it, under certain strict conditions, but it's not required to and doesn't support any "interesting" cases (ie changes in the number of slots).
But the case of method removal is easy: when a defmethod is evaluated, it will cause the original method with the same specializers to be overwritten. That, combined with the explanation that all accessors are always generated (but only sometimes used), should solve it.
 
But the runtime cost of doing so is huge, unfortunately: we can simply use DEFMETHOD to define the accessors. That will automatically notice the accessor is already defined and add a method for each additionally defined type.

[ snip ] 
I see multiple options:

1. Remove the type checks in the inline expansions
   and use DEFMETHOD for the accessor functions, where we need to use the methods
   only with sufficiently high SAFETY declarations
2. Use your patch to remove the type checks completely
3. Come up with a way to add dynamic type checks to the inline expansions and function definitions (ie not methods) - possibly executed conditionally with safety settings.
4. Do nothing (not saying it's a good option, but it's always an option)

Do you see any others?
Actually, I see one other solution, now that I had some time to think about it: we could trace back to the original type and be lenient and allow all descendants of that type access to the slot using the generated slot. That would allow both structures B and C to be read. According to the spec that's too lenient though:

The difference between the reader functions person-name and astro-name is that person-name can be correctly applied to any person, including anastronaut, while astro-name can be correctly applied only to an astronaut. An implementation might check for incorrect use of reader functions.
where "name" is a slot in the 'person' structure which is included in the 'astronaut' structure. 
Just to see what other implementations do: I ran this code on clisp (2.47) and it generates the same error. Apparently, the spec doesn't define this case and you can't depend on exact behaviour; the only thing I can find is a section on the relation between including and included structures, not between syblings:

Whether or not the :conc-name option is explicitly supplied, the following rule governs name conflicts of generated reader (or accessor) names: For any structuretype S1 having a reader function named R for a slot named X1 that is inherited by another structure type S2 that would have a reader function with the same name R for a slot named X2, no definition for R is generated by the definition of S2; instead, the definition of R is inherited from the definition of S1. (In such a case, if X1 and X2 are different slots, the implementation might signal a style warning.)

Which suggests that if you used FOO- for the nconc of the A structure as well, that all should be defined and well. Testing that on clisp and ABCL shows that it indeed is.
I'm not sure about the performance impact of dynamic checks, but I do think that if we decide to apply a caching strategy, using the slow-path of updating the cache in case of a type-mismatch, the impact may not be much worse than it is today. After all, the biggest change would be to generate code which allows to check more than one type instead of the current single type.
Given the performance impact of more complicated checks and the fact that structures are supposed to be geared for high performance (with classes being their flexible counter parts) *and* with the support (for my point) that I find in the spec and "other implementations" (i.e. clisp), I'd rather keep things the way they are at this time, although I'm open to input of the other developers of course.

Is it a solution for you to add the FOO- conc-name option to the A class as well?


Bye,

Erik.