Gauche > Archives > 2020/11/22

2020/11/22 18:43:20 UTCkaki
#
多重継承したサブクラスがあるとクラス再定義が class seems abandoned during class redefinition で落ちるみたいで、バグだと思い、ついでにクラス再定義への理解も深まるかと思ったので調査したものの今日のところは力尽きたので、ここに報告します。
#
gosh> (define-class <foo> () ())
<foo>
gosh> (define-class <bar> () ())
<bar>
gosh> (define-class <foobar> (<foo> <bar>) ())
<foobar>
gosh> (define-class <foo> () ())
<foo>
gosh> (define-class <bar> () ())
WARNING: Class redefinition of #<class <bar>> is aborted.  The state of the class may be inconsistent<bar>
#
(define-module foobar
  (export-all))

(select-module gauche.object)
(define-method class-redefinition ((old <class>) (new <class>))
  (define (d)
    (slot-ref-using-class <class> (with-module foobar <bar>) 'direct-subclasses))
  (format #t "class-redefinition start ~a ----->\n" new)
  #?=(d)
  (guard (e
          (else
           (report-error e)
           (raise e)))
    (for-each (^m (if (is-a? m <accessor-method>)
                      (delete-method! (slot-ref m 'generic) m)
                      (update-direct-method! m old new)))
              (class-direct-methods old))
    (for-each (^[sup]
                #?=(d)
                (print "  %delete-direct-subclass! " sup)
                (%delete-direct-subclass! sup old)
                #?=(d)
                )
              (class-direct-supers old))
    (for-each (^[sub]
                (print "  update-direct-subclass! " sub)
                (update-direct-subclass! sub old new))
              (class-direct-subclasses old)))
  #?=(d)
  (format #t "<----- class-redefinition end ~a\n" new))

(select-module foobar)

(define-class <foo> ()
  ())

(define-class <bar> ()
  ())

(define-class <foobar> (<foo> <bar>)
  ())
#
そこでこんなモジュールを用意すると reload で発火するので(というか元々は reload がうまくいかなくて困ってたんですが)
#
gosh> (reload 'foobar)
class-redefinition start #<class <foo>> ----->
#?=(d)
#?-    (#<class <foobar>>)
#?=(d)
#?-    (#<class <foobar>>)
  %delete-direct-subclass! #<class <object>>
#?=(d)
#?-    (#<class <foobar>>)
  update-direct-subclass! #<class <foobar>>
class-redefinition start #<class <foobar>> ----->
#?=(d)
#?-    (#<class <foobar>> #<class <foobar> (redefined)>)
#?=(d)
#?-    (#<class <foobar>> #<class <foobar> (redefined)>)
  %delete-direct-subclass! #<class <foo> (redefined)>
#?=(d)
#?-    (#<class <foobar>> #<class <foobar> (redefined)>)
#?=(d)
#?-    (#<class <foobar>> #<class <foobar> (redefined)>)
  %delete-direct-subclass! #<class <bar>>
#?=(d)
#?-    (#<class <foobar>>)
#?=(d)
#?-    (#<class <foobar>>)
  %delete-direct-subclass! #<class <object>>
#?=(d)
#?-    (#<class <foobar>>)
#?=(d)
#?-    (#<class <foobar>>)
<----- class-redefinition end #<class <foobar>>
#?=(d)
#?-    (#<class <foobar> (redefined)> #<class <foobar>>)
<----- class-redefinition end #<class <foo>>
class-redefinition start #<class <bar>> ----->
#?=(d)
#?-    (#<class <foobar> (redefined)> #<class <foobar>>)
#?=(d)
#?-    (#<class <foobar> (redefined)> #<class <foobar>>)
  %delete-direct-subclass! #<class <object>>
#?=(d)
#?-    (#<class <foobar> (redefined)> #<class <foobar>>)
  update-direct-subclass! #<class <foobar> (redefined)>
*** ERROR: class #<class <foobar> (redefined)> seems abandoned during class redefinition
以下略
2020/11/22 18:58:44 UTCkaki
#
で update-direct-subclass! の中で (%add-direct-subclass! sup sub) してるのが直接の原因に見えるんですが、そもそもこれは何故必要なのか…うーあー頭が回らない…という辺りで撤退しました。