bpo-41991: Remove _PyObject_HasAttrId (GH-22629)

It can silence arbitrary exceptions.
diff --git a/Include/cpython/object.h b/Include/cpython/object.h
index ae3920d..875a600 100644
--- a/Include/cpython/object.h
+++ b/Include/cpython/object.h
@@ -306,7 +306,6 @@
 PyAPI_FUNC(int) _PyObject_IsAbstract(PyObject *);
 PyAPI_FUNC(PyObject *) _PyObject_GetAttrId(PyObject *, struct _Py_Identifier *);
 PyAPI_FUNC(int) _PyObject_SetAttrId(PyObject *, struct _Py_Identifier *, PyObject *);
-PyAPI_FUNC(int) _PyObject_HasAttrId(PyObject *, struct _Py_Identifier *);
 /* Replacements of PyObject_GetAttr() and _PyObject_GetAttrId() which
    don't raise AttributeError.
 
diff --git a/Objects/object.c b/Objects/object.c
index 9889503..7bc3e48 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -855,17 +855,6 @@
 }
 
 int
-_PyObject_HasAttrId(PyObject *v, _Py_Identifier *name)
-{
-    int result;
-    PyObject *oname = _PyUnicode_FromId(name); /* borrowed */
-    if (!oname)
-        return -1;
-    result = PyObject_HasAttr(v, oname);
-    return result;
-}
-
-int
 _PyObject_SetAttrId(PyObject *v, _Py_Identifier *name, PyObject *w)
 {
     int result;
diff --git a/Objects/unionobject.c b/Objects/unionobject.c
index 8cfb2a6..89fdaf4 100644
--- a/Objects/unionobject.c
+++ b/Objects/unionobject.c
@@ -311,21 +311,22 @@
     _Py_IDENTIFIER(__args__);
     PyObject *qualname = NULL;
     PyObject *module = NULL;
+    PyObject *tmp;
     PyObject *r = NULL;
     int err;
 
-    int has_origin = _PyObject_HasAttrId(p, &PyId___origin__);
-    if (has_origin < 0) {
+    if (_PyObject_LookupAttrId(p, &PyId___origin__, &tmp) < 0) {
         goto exit;
     }
 
-    if (has_origin) {
-        int has_args = _PyObject_HasAttrId(p, &PyId___args__);
-        if (has_args < 0) {
+    if (tmp) {
+        Py_DECREF(tmp);
+        if (_PyObject_LookupAttrId(p, &PyId___args__, &tmp) < 0) {
             goto exit;
         }
-        if (has_args) {
+        if (tmp) {
             // It looks like a GenericAlias
+            Py_DECREF(tmp);
             goto use_repr;
         }
     }
diff --git a/Python/errors.c b/Python/errors.c
index 720f18b..02cf479 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -1593,9 +1593,18 @@
             }
             Py_DECREF(tmp);
         }
+        else {
+            _PyErr_Clear(tstate);
+        }
     }
     if (exc != PyExc_SyntaxError) {
-        if (!_PyObject_HasAttrId(v, &PyId_msg)) {
+        if (_PyObject_LookupAttrId(v, &PyId_msg, &tmp) < 0) {
+            _PyErr_Clear(tstate);
+        }
+        else if (tmp) {
+            Py_DECREF(tmp);
+        }
+        else {
             tmp = PyObject_Str(v);
             if (tmp) {
                 if (_PyObject_SetAttrId(v, &PyId_msg, tmp)) {
@@ -1607,7 +1616,13 @@
                 _PyErr_Clear(tstate);
             }
         }
-        if (!_PyObject_HasAttrId(v, &PyId_print_file_and_line)) {
+        if (_PyObject_LookupAttrId(v, &PyId_print_file_and_line, &tmp) < 0) {
+            _PyErr_Clear(tstate);
+        }
+        else if (tmp) {
+            Py_DECREF(tmp);
+        }
+        else {
             if (_PyObject_SetAttrId(v, &PyId_print_file_and_line,
                                     Py_None)) {
                 _PyErr_Clear(tstate);
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index ff80103..a45ca3b 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -770,7 +770,7 @@
 print_exception(PyObject *f, PyObject *value)
 {
     int err = 0;
-    PyObject *type, *tb;
+    PyObject *type, *tb, *tmp;
     _Py_IDENTIFIER(print_file_and_line);
 
     if (!PyExceptionInstance_Check(value)) {
@@ -789,10 +789,12 @@
     if (tb && tb != Py_None)
         err = PyTraceBack_Print(tb, f);
     if (err == 0 &&
-        _PyObject_HasAttrId(value, &PyId_print_file_and_line))
+        (err = _PyObject_LookupAttrId(value, &PyId_print_file_and_line, &tmp)) > 0)
     {
         PyObject *message, *filename, *text;
         Py_ssize_t lineno, offset;
+        err = 0;
+        Py_DECREF(tmp);
         if (!parse_syntax_error(value, &message, &filename,
                                 &lineno, &offset, &text))
             PyErr_Clear();