move_finalizers():  Rewrote.  It's not necessary for this routine to special-case classic classes, or to worry about refcounts; has_finalizer() deleted the current object iff the first entry in the unreachable list has changed.  I don't believe it was correct to check for ob_refcnt == 1, either:  the dealloc routine would get called by Py_DECREF then, but there's nothing to stop the dealloc routine from ressurecting the object, and then gc would remain at the head of the unreachable list despite that its refcount temporarily fell to 0 (and that would lead to an infinite loop in move_finalizers()).
move_finalizers():  Rewrote.  It's not necessary for this routine
to special-case classic classes, or to worry about refcounts;
has_finalizer() deleted the current object iff the first entry in
the unreachable list has changed.  I don't believe it was correct
to check for ob_refcnt == 1, either:  the dealloc routine would get
called by Py_DECREF then, but there's nothing to stop the dealloc
routine from ressurecting the object, and then gc would remain at
the head of the unreachable list despite that its refcount temporarily
fell to 0 (and that would lead to an infinite loop in move_finalizers()).

I'm still worried about has_finalizer() resurrecting other objects
in the unreachable list:  what's to stop them from getting collected?

sk-/python2.7-type-annotator,sk-/python2.7-type-annotator,sk-/python2.7-type-annotator