Fix crash in astdiff and clean it up (#14497)
Ref #14329
This fixes one of the crashes reported in the issue. In fact, using
recursive type caught this crash statically, plus another subtle crash
in `snapshot_optional_type()`, _without a single false positive_ (I was
able to cleanly type also symbol table snapshots, but decided it is not
worth the churn since we only ever compare them with `==`, supported by
~every Python object). I feel triumphant :-)