bpo-44606: Fix __instancecheck__ and __subclasscheck__ for the union type. (GH-27120)


* Fix issubclass() for None.
  E.g. issubclass(type(None), int | None) returns now True.
* Fix issubclass() for virtual subclasses.
  E.g. issubclass(dict, int | collections.abc.Mapping) returns now True.
* Fix crash in isinstance() if the check for one of items raises exception.
(cherry picked from commit 81989058de381108dfd0a4255b93d4fb34417002)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
diff --git a/Objects/unionobject.c b/Objects/unionobject.c
index 8435763..bcba0f6 100644
--- a/Objects/unionobject.c
+++ b/Objects/unionobject.c
@@ -67,8 +67,14 @@ union_instancecheck(PyObject *self, PyObject *instance)
         if (arg == Py_None) {
             arg = (PyObject *)&_PyNone_Type;
         }
-        if (PyType_Check(arg) && PyObject_IsInstance(instance, arg) != 0) {
-            Py_RETURN_TRUE;
+        if (PyType_Check(arg)) {
+            int res = PyObject_IsInstance(instance, arg);
+            if (res < 0) {
+                return NULL;
+            }
+            if (res) {
+                Py_RETURN_TRUE;
+            }
         }
     }
     Py_RETURN_FALSE;
@@ -90,8 +96,17 @@ union_subclasscheck(PyObject *self, PyObject *instance)
     Py_ssize_t nargs = PyTuple_GET_SIZE(alias->args);
     for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
         PyObject *arg = PyTuple_GET_ITEM(alias->args, iarg);
-        if (PyType_Check(arg) && (PyType_IsSubtype((PyTypeObject *)instance, (PyTypeObject *)arg) != 0)) {
-            Py_RETURN_TRUE;
+        if (arg == Py_None) {
+            arg = (PyObject *)&_PyNone_Type;
+        }
+        if (PyType_Check(arg)) {
+            int res = PyObject_IsSubclass(instance, arg);
+            if (res < 0) {
+                return NULL;
+            }
+            if (res) {
+                Py_RETURN_TRUE;
+            }
         }
     }
    Py_RETURN_FALSE;