mrd wrote:
> As far as I can tell, though I can't seem to find an exact reference for
> it in AMOP or CLHS, classes don't need to be finalized immediately. I
> believe the requirement is that they be finalized no later than creation
> of an instance of said class. Since classes can forward-reference
> supers, this seems to make sense.
>
> If you wish to invoke MOP functionality that requires a finalized class,
> you may want to precede it with a call to sb-mop:finalize-inheritance.
>
You know, I had not noticed if it would not appear to be explicitly called
for, in the specification for the protocol.
I think it is an implicit requirement -- judging this directly on the AMOP
specification, now -- that a class will be finalized as soon as possible.
AMOP has the following, under the section "Class Finalization Protocol".
---------------------------------------------------------------
The exact point at which finalize-inheritance is called depends on the class
of the class metaobject; for standard-class it is called sometime after all
the classes superclasses are defined, but no later than when the first
instance of the class is allocated (by allocate-instance).
---------------------------------------------------------------
That statement serves to establish a range in which FINALIZE-INHERITANCE
must be called. Undoubtedly, SBCL is meeting the requirement specified in
that statement.
Again in AMOP, under the section "Readers for Class Metaobjects", the
following is stated.
---------------------------------------------------------------
Each entry in the table indicates a method on one of the reader generic
functions, specialized to a specified class. The number in each entry is a
reference to the full description of the method. The full descriptions
appear after the table.
standard-class and funcallable-standard-class
forward-referenced-class
built-in-class
class-default-initargs 2 3 4
class-direct-default-initargs 1 4 4
class-direct-slots 1 4 4
class-direct-subclasses 9 9 7
class-direct-superclasses 1 4 7
class-finalized-p 2 6 5
class-name 1 1 8
class-precedence-list 2 3 7
class-prototype 10 10 10
class-slots 2 3 4
1. This method returns the value which was associated with the class
metaobject during initialization or reinitialization.
2. This method returns the value associated with the class metaobject by
finalize-inheritance (standard-class) or finalize-inheritance
(funcallable-standard-class).
3. This method signals an error.
---------------------------------------------------------------
The behavior specified for CLASS-SLOTS, on STANDARD-CLASS and
FUNCALLABLE-STANDARD-CLASS -- that it must be the result occurring after
FINALIZE-INHERITANCE -- that would appear to require that
FINALIZE-INHERITANCE would be called on a class of such a type, as before
CLASS-SLOTS would be called.
Granted, that does not say like "Call finalize-inheritance on the class, as
soon as the class is eligible for finalization". Such a behavior, though,
it would certainly meet the word of the specification.
In order to accomplish the specified ends, I'd propose that finalize-class
would be called -- when the instance would be eligible for finalization --
then as during the SHARED-INITIALIZE :AFTER (STD-CLASS) method defined in
PCL. I'd propose that it would be included, there, as for purpose of making
the behavior consistent across class implementations.
I've attached a diff, applicable for implementing a
finalize-as-soon-as-eligible behavior in SBCL, in direct application onto
the SB-PCL source tree. I've applied the patched code; I have not noticed
any problems of it.
The lisp-text file, attached second to the diff, it would be operable for
implementing a finalize-as-soon-as-eligible behavior in the implementation,
using a class THE-PROTOCOL-CLASS, and without patching the matter into
SB-PCL.
--
Sean Champ

Thread view

In a most recent build of SBCL, compiled on sources checked-out last night,
something is going wrong about class finalization.
Notice that the following DEFCLASS call does not result in a finalized
class.
-------------------------------------
* (lisp-implementation-version)
"0.9.15.48"
* (defclass a () ((b)))
#<STANDARD-CLASS A>
* (describe 'a)
A is an internal symbol in #<PACKAGE "COMMON-LISP-USER">.
It names a class #<STANDARD-CLASS A>.
#<STANDARD-CLASS A> is a class. It is an instance of STANDARD-CLASS.
Its proper name is A.
The direct superclasses are: (STANDARD-OBJECT), and the direct subclasses
are:
().
The class is not finalized; its class precedence list is:
(A STANDARD-OBJECT SB-PCL::SLOT-OBJECT T).
There are 0 methods specialized for this class.
-------------------------------------
The non-finalization behavior can causes problems, in systems operating on
class slots. That's how I came to notice it, in SBCL 0.9.15.
-------------------------------------
* (sb-mop::class-slots (defclass b () ((c) (d))))
NIL
-------------------------------------
It appears that something about the combination of a call to FIND-CLASS and
a call to DESCRIBE *might* result in that the class will become finalized.
The following demonstrates an instance of such -- but the example after
this one does not.
-------------------------------------
* (defclass c () ())
#<STANDARD-CLASS C>
* (describe 'c)
C is an internal symbol in #<PACKAGE "COMMON-LISP-USER">.
It names a class #<STANDARD-CLASS C>.
#<STANDARD-CLASS C> is a class. It is an instance of STANDARD-CLASS.
Its proper name is C.
The direct superclasses are: (STANDARD-OBJECT), and the direct subclasses
are:
().
The class is not finalized; its class precedence list is:
(C STANDARD-OBJECT SB-PCL::SLOT-OBJECT T).
There are 0 methods specialized for this class.
* (find-class 'c)
#<STANDARD-CLASS C>
* (describe 'c)
C is an internal symbol in #<PACKAGE "COMMON-LISP-USER">.
It names a class #<STANDARD-CLASS C>.
#<STANDARD-CLASS C> is a class. It is an instance of STANDARD-CLASS.
Its proper name is C.
The direct superclasses are: (STANDARD-OBJECT), and the direct subclasses
are:
().
The class is finalized; its class precedence list is:
(C STANDARD-OBJECT SB-PCL::SLOT-OBJECT T).
There are 0 methods specialized for this class.
-------------------------------------
Maybe the following would be of any help in figuring out what's going wrong?
Notice when the trace routine results in a message output -- during
DESCRIBE.
Furthermore, the class does not appear to become finalized in the process of
this.
-------------------------------------
* (trace sb-mop:effective-slot-definition-class)
(SB-MOP:EFFECTIVE-SLOT-DEFINITION-CLASS)
* (Defclass d () ((a)))
#<STANDARD-CLASS D>
* (find-class 'd)
#<STANDARD-CLASS D>
* (sb-mop::class-slots (find-class 'd))
NIL
* (describe 'd)
D is an internal symbol in #<PACKAGE "COMMON-LISP-USER">.
It names a class #<STANDARD-CLASS D>.
#<STANDARD-CLASS D> is a class. It is an instance of STANDARD-CLASS.
Its proper name is D. 0: (SB-MOP:EFFECTIVE-SLOT-DEFINITION-CLASS
#<STANDARD-CLASS D> :NAME A
:INITFORM NIL :INITFUNCTION NIL
:INITARGS NIL :ALLOCATION
:INSTANCE :ALLOCATION-CLASS
#<STANDARD-CLASS D> :TYPE
T :CLASS
#<STANDARD-CLASS
D> :DOCUMENTATION
NIL)
0: SB-MOP:EFFECTIVE-SLOT-DEFINITION-CLASS returned
#<STANDARD-CLASS SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION>
The direct superclasses are: (STANDARD-OBJECT), and the direct subclasses
are:
().
The class is not finalized; its class precedence list is:
(D STANDARD-OBJECT SB-PCL::SLOT-OBJECT T).
There are 0 methods specialized for this class.
-------------------------------------
Calling the following, immediately after that, it then results in that the
class becomes finalized:
-------------------------------------
* (describe 'd)
D is an internal symbol in #<PACKAGE "COMMON-LISP-USER">.
It names a class #<STANDARD-CLASS D>.
#<STANDARD-CLASS D> is a class. It is an instance of STANDARD-CLASS.
Its proper name is D.
The direct superclasses are: (STANDARD-OBJECT), and the direct subclasses
are:
().
The class is finalized; its class precedence list is:
(D STANDARD-OBJECT SB-PCL::SLOT-OBJECT T).
There are 0 methods specialized for this class.
-------------------------------------
I'm not sure what's going wrong. I'm not much familiar with SB-PCL, though I
hope to resolve that, in more.
Here's one more note, for what it's worth. UPDATE-CLASS is being called, but
with a NIL second argument.
-------------------------------------
* (trace sb-pcl::update-class)
(SB-PCL::UPDATE-CLASS)
* (defclass e () ())
0: (SB-PCL::UPDATE-CLASS #<STANDARD-CLASS E> NIL)
0: SB-PCL::UPDATE-CLASS returned NIL
#<STANDARD-CLASS E>
* (describe 'e)
E is an internal symbol in #<PACKAGE "COMMON-LISP-USER">.
It names a class #<STANDARD-CLASS E>.
#<STANDARD-CLASS E> is a class. It is an instance of STANDARD-CLASS.
Its proper name is E. 0: (SB-PCL::UPDATE-CLASS #<STANDARD-CLASS E> T)
0: SB-PCL::UPDATE-CLASS returned NIL
The direct superclasses are: (STANDARD-OBJECT), and the direct subclasses
are:
().
The class is not finalized; its class precedence list is:
(E STANDARD-OBJECT SB-PCL::SLOT-OBJECT T).
There are 0 methods specialized for this class.
-------------------------------------
I thought that this issue would bear mention.
One question, by the wayside: What would be an appropriate means by which to
add a check about this issue, into the SBCL tests?
--
Sean Champ

On Fri, Aug 25, 2006 at 09:09:37AM -0700, Sean Champ wrote:
> In a most recent build of SBCL, compiled on sources checked-out last night,
> something is going wrong about class finalization.
>
> Notice that the following DEFCLASS call does not result in a finalized
> class.
[snip]
I've read and reread your message but fail to see what is going
wrong. Can you point me to the chapter and verse of MOP which is being
violated?
> One question, by the wayside: What would be an appropriate means by which to
> add a check about this issue, into the SBCL tests?
Why would we add a check for something which was deliberately
introduced in a recent version of SBCL? See
http://www.sbcl.org/news.html#0.9.15 .
--
Brian Mastenbrook
brian@...
http://brian.mastenbrook.net/

As far as I can tell, though I can't seem to find an exact reference for
it in AMOP or CLHS, classes don't need to be finalized immediately. I
believe the requirement is that they be finalized no later than creation
of an instance of said class. Since classes can forward-reference
supers, this seems to make sense.
If you wish to invoke MOP functionality that requires a finalized class,
you may want to precede it with a call to sb-mop:finalize-inheritance.
--
;; Matthew Danish -- user: mrd domain: cmu.edu
;; OpenPGP public key: C24B6010 on keyring.debian.org

mrd wrote:
> As far as I can tell, though I can't seem to find an exact reference for
> it in AMOP or CLHS, classes don't need to be finalized immediately. I
> believe the requirement is that they be finalized no later than creation
> of an instance of said class. Since classes can forward-reference
> supers, this seems to make sense.
>
> If you wish to invoke MOP functionality that requires a finalized class,
> you may want to precede it with a call to sb-mop:finalize-inheritance.
>
You know, I had not noticed if it would not appear to be explicitly called
for, in the specification for the protocol.
I think it is an implicit requirement -- judging this directly on the AMOP
specification, now -- that a class will be finalized as soon as possible.
AMOP has the following, under the section "Class Finalization Protocol".
---------------------------------------------------------------
The exact point at which finalize-inheritance is called depends on the class
of the class metaobject; for standard-class it is called sometime after all
the classes superclasses are defined, but no later than when the first
instance of the class is allocated (by allocate-instance).
---------------------------------------------------------------
That statement serves to establish a range in which FINALIZE-INHERITANCE
must be called. Undoubtedly, SBCL is meeting the requirement specified in
that statement.
Again in AMOP, under the section "Readers for Class Metaobjects", the
following is stated.
---------------------------------------------------------------
Each entry in the table indicates a method on one of the reader generic
functions, specialized to a specified class. The number in each entry is a
reference to the full description of the method. The full descriptions
appear after the table.
standard-class and funcallable-standard-class
forward-referenced-class
built-in-class
class-default-initargs 2 3 4
class-direct-default-initargs 1 4 4
class-direct-slots 1 4 4
class-direct-subclasses 9 9 7
class-direct-superclasses 1 4 7
class-finalized-p 2 6 5
class-name 1 1 8
class-precedence-list 2 3 7
class-prototype 10 10 10
class-slots 2 3 4
1. This method returns the value which was associated with the class
metaobject during initialization or reinitialization.
2. This method returns the value associated with the class metaobject by
finalize-inheritance (standard-class) or finalize-inheritance
(funcallable-standard-class).
3. This method signals an error.
---------------------------------------------------------------
The behavior specified for CLASS-SLOTS, on STANDARD-CLASS and
FUNCALLABLE-STANDARD-CLASS -- that it must be the result occurring after
FINALIZE-INHERITANCE -- that would appear to require that
FINALIZE-INHERITANCE would be called on a class of such a type, as before
CLASS-SLOTS would be called.
Granted, that does not say like "Call finalize-inheritance on the class, as
soon as the class is eligible for finalization". Such a behavior, though,
it would certainly meet the word of the specification.
In order to accomplish the specified ends, I'd propose that finalize-class
would be called -- when the instance would be eligible for finalization --
then as during the SHARED-INITIALIZE :AFTER (STD-CLASS) method defined in
PCL. I'd propose that it would be included, there, as for purpose of making
the behavior consistent across class implementations.
I've attached a diff, applicable for implementing a
finalize-as-soon-as-eligible behavior in SBCL, in direct application onto
the SB-PCL source tree. I've applied the patched code; I have not noticed
any problems of it.
The lisp-text file, attached second to the diff, it would be operable for
implementing a finalize-as-soon-as-eligible behavior in the implementation,
using a class THE-PROTOCOL-CLASS, and without patching the matter into
SB-PCL.
--
Sean Champ