17db96d56Sopenharmony_ci// types.GenericAlias -- used to represent e.g. list[int].
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci#include "Python.h"
47db96d56Sopenharmony_ci#include "pycore_object.h"
57db96d56Sopenharmony_ci#include "pycore_unionobject.h"   // _Py_union_type_or, _PyGenericAlias_Check
67db96d56Sopenharmony_ci#include "structmember.h"         // PyMemberDef
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_ci#include <stdbool.h>
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_citypedef struct {
117db96d56Sopenharmony_ci    PyObject_HEAD
127db96d56Sopenharmony_ci    PyObject *origin;
137db96d56Sopenharmony_ci    PyObject *args;
147db96d56Sopenharmony_ci    PyObject *parameters;
157db96d56Sopenharmony_ci    PyObject *weakreflist;
167db96d56Sopenharmony_ci    // Whether we're a starred type, e.g. *tuple[int].
177db96d56Sopenharmony_ci    bool starred;
187db96d56Sopenharmony_ci    vectorcallfunc vectorcall;
197db96d56Sopenharmony_ci} gaobject;
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_citypedef struct {
227db96d56Sopenharmony_ci    PyObject_HEAD
237db96d56Sopenharmony_ci    PyObject *obj;  /* Set to NULL when iterator is exhausted */
247db96d56Sopenharmony_ci} gaiterobject;
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_cistatic void
277db96d56Sopenharmony_ciga_dealloc(PyObject *self)
287db96d56Sopenharmony_ci{
297db96d56Sopenharmony_ci    gaobject *alias = (gaobject *)self;
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_ci    _PyObject_GC_UNTRACK(self);
327db96d56Sopenharmony_ci    if (alias->weakreflist != NULL) {
337db96d56Sopenharmony_ci        PyObject_ClearWeakRefs((PyObject *)alias);
347db96d56Sopenharmony_ci    }
357db96d56Sopenharmony_ci    Py_XDECREF(alias->origin);
367db96d56Sopenharmony_ci    Py_XDECREF(alias->args);
377db96d56Sopenharmony_ci    Py_XDECREF(alias->parameters);
387db96d56Sopenharmony_ci    Py_TYPE(self)->tp_free(self);
397db96d56Sopenharmony_ci}
407db96d56Sopenharmony_ci
417db96d56Sopenharmony_cistatic int
427db96d56Sopenharmony_ciga_traverse(PyObject *self, visitproc visit, void *arg)
437db96d56Sopenharmony_ci{
447db96d56Sopenharmony_ci    gaobject *alias = (gaobject *)self;
457db96d56Sopenharmony_ci    Py_VISIT(alias->origin);
467db96d56Sopenharmony_ci    Py_VISIT(alias->args);
477db96d56Sopenharmony_ci    Py_VISIT(alias->parameters);
487db96d56Sopenharmony_ci    return 0;
497db96d56Sopenharmony_ci}
507db96d56Sopenharmony_ci
517db96d56Sopenharmony_cistatic int
527db96d56Sopenharmony_ciga_repr_item(_PyUnicodeWriter *writer, PyObject *p)
537db96d56Sopenharmony_ci{
547db96d56Sopenharmony_ci    PyObject *qualname = NULL;
557db96d56Sopenharmony_ci    PyObject *module = NULL;
567db96d56Sopenharmony_ci    PyObject *r = NULL;
577db96d56Sopenharmony_ci    PyObject *tmp;
587db96d56Sopenharmony_ci    int err;
597db96d56Sopenharmony_ci
607db96d56Sopenharmony_ci    if (p == Py_Ellipsis) {
617db96d56Sopenharmony_ci        // The Ellipsis object
627db96d56Sopenharmony_ci        r = PyUnicode_FromString("...");
637db96d56Sopenharmony_ci        goto done;
647db96d56Sopenharmony_ci    }
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_ci    if (_PyObject_LookupAttr(p, &_Py_ID(__origin__), &tmp) < 0) {
677db96d56Sopenharmony_ci        goto done;
687db96d56Sopenharmony_ci    }
697db96d56Sopenharmony_ci    if (tmp != NULL) {
707db96d56Sopenharmony_ci        Py_DECREF(tmp);
717db96d56Sopenharmony_ci        if (_PyObject_LookupAttr(p, &_Py_ID(__args__), &tmp) < 0) {
727db96d56Sopenharmony_ci            goto done;
737db96d56Sopenharmony_ci        }
747db96d56Sopenharmony_ci        if (tmp != NULL) {
757db96d56Sopenharmony_ci            Py_DECREF(tmp);
767db96d56Sopenharmony_ci            // It looks like a GenericAlias
777db96d56Sopenharmony_ci            goto use_repr;
787db96d56Sopenharmony_ci        }
797db96d56Sopenharmony_ci    }
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci    if (_PyObject_LookupAttr(p, &_Py_ID(__qualname__), &qualname) < 0) {
827db96d56Sopenharmony_ci        goto done;
837db96d56Sopenharmony_ci    }
847db96d56Sopenharmony_ci    if (qualname == NULL) {
857db96d56Sopenharmony_ci        goto use_repr;
867db96d56Sopenharmony_ci    }
877db96d56Sopenharmony_ci    if (_PyObject_LookupAttr(p, &_Py_ID(__module__), &module) < 0) {
887db96d56Sopenharmony_ci        goto done;
897db96d56Sopenharmony_ci    }
907db96d56Sopenharmony_ci    if (module == NULL || module == Py_None) {
917db96d56Sopenharmony_ci        goto use_repr;
927db96d56Sopenharmony_ci    }
937db96d56Sopenharmony_ci
947db96d56Sopenharmony_ci    // Looks like a class
957db96d56Sopenharmony_ci    if (PyUnicode_Check(module) &&
967db96d56Sopenharmony_ci        _PyUnicode_EqualToASCIIString(module, "builtins"))
977db96d56Sopenharmony_ci    {
987db96d56Sopenharmony_ci        // builtins don't need a module name
997db96d56Sopenharmony_ci        r = PyObject_Str(qualname);
1007db96d56Sopenharmony_ci        goto done;
1017db96d56Sopenharmony_ci    }
1027db96d56Sopenharmony_ci    else {
1037db96d56Sopenharmony_ci        r = PyUnicode_FromFormat("%S.%S", module, qualname);
1047db96d56Sopenharmony_ci        goto done;
1057db96d56Sopenharmony_ci    }
1067db96d56Sopenharmony_ci
1077db96d56Sopenharmony_ciuse_repr:
1087db96d56Sopenharmony_ci    r = PyObject_Repr(p);
1097db96d56Sopenharmony_ci
1107db96d56Sopenharmony_cidone:
1117db96d56Sopenharmony_ci    Py_XDECREF(qualname);
1127db96d56Sopenharmony_ci    Py_XDECREF(module);
1137db96d56Sopenharmony_ci    if (r == NULL) {
1147db96d56Sopenharmony_ci        // error if any of the above PyObject_Repr/PyUnicode_From* fail
1157db96d56Sopenharmony_ci        err = -1;
1167db96d56Sopenharmony_ci    }
1177db96d56Sopenharmony_ci    else {
1187db96d56Sopenharmony_ci        err = _PyUnicodeWriter_WriteStr(writer, r);
1197db96d56Sopenharmony_ci        Py_DECREF(r);
1207db96d56Sopenharmony_ci    }
1217db96d56Sopenharmony_ci    return err;
1227db96d56Sopenharmony_ci}
1237db96d56Sopenharmony_ci
1247db96d56Sopenharmony_cistatic PyObject *
1257db96d56Sopenharmony_ciga_repr(PyObject *self)
1267db96d56Sopenharmony_ci{
1277db96d56Sopenharmony_ci    gaobject *alias = (gaobject *)self;
1287db96d56Sopenharmony_ci    Py_ssize_t len = PyTuple_GET_SIZE(alias->args);
1297db96d56Sopenharmony_ci
1307db96d56Sopenharmony_ci    _PyUnicodeWriter writer;
1317db96d56Sopenharmony_ci    _PyUnicodeWriter_Init(&writer);
1327db96d56Sopenharmony_ci
1337db96d56Sopenharmony_ci    if (alias->starred) {
1347db96d56Sopenharmony_ci        if (_PyUnicodeWriter_WriteASCIIString(&writer, "*", 1) < 0) {
1357db96d56Sopenharmony_ci            goto error;
1367db96d56Sopenharmony_ci        }
1377db96d56Sopenharmony_ci    }
1387db96d56Sopenharmony_ci    if (ga_repr_item(&writer, alias->origin) < 0) {
1397db96d56Sopenharmony_ci        goto error;
1407db96d56Sopenharmony_ci    }
1417db96d56Sopenharmony_ci    if (_PyUnicodeWriter_WriteASCIIString(&writer, "[", 1) < 0) {
1427db96d56Sopenharmony_ci        goto error;
1437db96d56Sopenharmony_ci    }
1447db96d56Sopenharmony_ci    for (Py_ssize_t i = 0; i < len; i++) {
1457db96d56Sopenharmony_ci        if (i > 0) {
1467db96d56Sopenharmony_ci            if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) {
1477db96d56Sopenharmony_ci                goto error;
1487db96d56Sopenharmony_ci            }
1497db96d56Sopenharmony_ci        }
1507db96d56Sopenharmony_ci        PyObject *p = PyTuple_GET_ITEM(alias->args, i);
1517db96d56Sopenharmony_ci        if (ga_repr_item(&writer, p) < 0) {
1527db96d56Sopenharmony_ci            goto error;
1537db96d56Sopenharmony_ci        }
1547db96d56Sopenharmony_ci    }
1557db96d56Sopenharmony_ci    if (len == 0) {
1567db96d56Sopenharmony_ci        // for something like tuple[()] we should print a "()"
1577db96d56Sopenharmony_ci        if (_PyUnicodeWriter_WriteASCIIString(&writer, "()", 2) < 0) {
1587db96d56Sopenharmony_ci            goto error;
1597db96d56Sopenharmony_ci        }
1607db96d56Sopenharmony_ci    }
1617db96d56Sopenharmony_ci    if (_PyUnicodeWriter_WriteASCIIString(&writer, "]", 1) < 0) {
1627db96d56Sopenharmony_ci        goto error;
1637db96d56Sopenharmony_ci    }
1647db96d56Sopenharmony_ci    return _PyUnicodeWriter_Finish(&writer);
1657db96d56Sopenharmony_cierror:
1667db96d56Sopenharmony_ci    _PyUnicodeWriter_Dealloc(&writer);
1677db96d56Sopenharmony_ci    return NULL;
1687db96d56Sopenharmony_ci}
1697db96d56Sopenharmony_ci
1707db96d56Sopenharmony_ci// Index of item in self[:len], or -1 if not found (self is a tuple)
1717db96d56Sopenharmony_cistatic Py_ssize_t
1727db96d56Sopenharmony_cituple_index(PyObject *self, Py_ssize_t len, PyObject *item)
1737db96d56Sopenharmony_ci{
1747db96d56Sopenharmony_ci    for (Py_ssize_t i = 0; i < len; i++) {
1757db96d56Sopenharmony_ci        if (PyTuple_GET_ITEM(self, i) == item) {
1767db96d56Sopenharmony_ci            return i;
1777db96d56Sopenharmony_ci        }
1787db96d56Sopenharmony_ci    }
1797db96d56Sopenharmony_ci    return -1;
1807db96d56Sopenharmony_ci}
1817db96d56Sopenharmony_ci
1827db96d56Sopenharmony_cistatic int
1837db96d56Sopenharmony_cituple_add(PyObject *self, Py_ssize_t len, PyObject *item)
1847db96d56Sopenharmony_ci{
1857db96d56Sopenharmony_ci    if (tuple_index(self, len, item) < 0) {
1867db96d56Sopenharmony_ci        Py_INCREF(item);
1877db96d56Sopenharmony_ci        PyTuple_SET_ITEM(self, len, item);
1887db96d56Sopenharmony_ci        return 1;
1897db96d56Sopenharmony_ci    }
1907db96d56Sopenharmony_ci    return 0;
1917db96d56Sopenharmony_ci}
1927db96d56Sopenharmony_ci
1937db96d56Sopenharmony_cistatic Py_ssize_t
1947db96d56Sopenharmony_cituple_extend(PyObject **dst, Py_ssize_t dstindex,
1957db96d56Sopenharmony_ci             PyObject **src, Py_ssize_t count)
1967db96d56Sopenharmony_ci{
1977db96d56Sopenharmony_ci    assert(count >= 0);
1987db96d56Sopenharmony_ci    if (_PyTuple_Resize(dst, PyTuple_GET_SIZE(*dst) + count - 1) != 0) {
1997db96d56Sopenharmony_ci        return -1;
2007db96d56Sopenharmony_ci    }
2017db96d56Sopenharmony_ci    assert(dstindex + count <= PyTuple_GET_SIZE(*dst));
2027db96d56Sopenharmony_ci    for (Py_ssize_t i = 0; i < count; ++i) {
2037db96d56Sopenharmony_ci        PyObject *item = src[i];
2047db96d56Sopenharmony_ci        Py_INCREF(item);
2057db96d56Sopenharmony_ci        PyTuple_SET_ITEM(*dst, dstindex + i, item);
2067db96d56Sopenharmony_ci    }
2077db96d56Sopenharmony_ci    return dstindex + count;
2087db96d56Sopenharmony_ci}
2097db96d56Sopenharmony_ci
2107db96d56Sopenharmony_ciPyObject *
2117db96d56Sopenharmony_ci_Py_make_parameters(PyObject *args)
2127db96d56Sopenharmony_ci{
2137db96d56Sopenharmony_ci    Py_ssize_t nargs = PyTuple_GET_SIZE(args);
2147db96d56Sopenharmony_ci    Py_ssize_t len = nargs;
2157db96d56Sopenharmony_ci    PyObject *parameters = PyTuple_New(len);
2167db96d56Sopenharmony_ci    if (parameters == NULL)
2177db96d56Sopenharmony_ci        return NULL;
2187db96d56Sopenharmony_ci    Py_ssize_t iparam = 0;
2197db96d56Sopenharmony_ci    for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
2207db96d56Sopenharmony_ci        PyObject *t = PyTuple_GET_ITEM(args, iarg);
2217db96d56Sopenharmony_ci        PyObject *subst;
2227db96d56Sopenharmony_ci        // We don't want __parameters__ descriptor of a bare Python class.
2237db96d56Sopenharmony_ci        if (PyType_Check(t)) {
2247db96d56Sopenharmony_ci            continue;
2257db96d56Sopenharmony_ci        }
2267db96d56Sopenharmony_ci        if (_PyObject_LookupAttr(t, &_Py_ID(__typing_subst__), &subst) < 0) {
2277db96d56Sopenharmony_ci            Py_DECREF(parameters);
2287db96d56Sopenharmony_ci            return NULL;
2297db96d56Sopenharmony_ci        }
2307db96d56Sopenharmony_ci        if (subst) {
2317db96d56Sopenharmony_ci            iparam += tuple_add(parameters, iparam, t);
2327db96d56Sopenharmony_ci            Py_DECREF(subst);
2337db96d56Sopenharmony_ci        }
2347db96d56Sopenharmony_ci        else {
2357db96d56Sopenharmony_ci            PyObject *subparams;
2367db96d56Sopenharmony_ci            if (_PyObject_LookupAttr(t, &_Py_ID(__parameters__),
2377db96d56Sopenharmony_ci                                     &subparams) < 0) {
2387db96d56Sopenharmony_ci                Py_DECREF(parameters);
2397db96d56Sopenharmony_ci                return NULL;
2407db96d56Sopenharmony_ci            }
2417db96d56Sopenharmony_ci            if (subparams && PyTuple_Check(subparams)) {
2427db96d56Sopenharmony_ci                Py_ssize_t len2 = PyTuple_GET_SIZE(subparams);
2437db96d56Sopenharmony_ci                Py_ssize_t needed = len2 - 1 - (iarg - iparam);
2447db96d56Sopenharmony_ci                if (needed > 0) {
2457db96d56Sopenharmony_ci                    len += needed;
2467db96d56Sopenharmony_ci                    if (_PyTuple_Resize(&parameters, len) < 0) {
2477db96d56Sopenharmony_ci                        Py_DECREF(subparams);
2487db96d56Sopenharmony_ci                        Py_DECREF(parameters);
2497db96d56Sopenharmony_ci                        return NULL;
2507db96d56Sopenharmony_ci                    }
2517db96d56Sopenharmony_ci                }
2527db96d56Sopenharmony_ci                for (Py_ssize_t j = 0; j < len2; j++) {
2537db96d56Sopenharmony_ci                    PyObject *t2 = PyTuple_GET_ITEM(subparams, j);
2547db96d56Sopenharmony_ci                    iparam += tuple_add(parameters, iparam, t2);
2557db96d56Sopenharmony_ci                }
2567db96d56Sopenharmony_ci            }
2577db96d56Sopenharmony_ci            Py_XDECREF(subparams);
2587db96d56Sopenharmony_ci        }
2597db96d56Sopenharmony_ci    }
2607db96d56Sopenharmony_ci    if (iparam < len) {
2617db96d56Sopenharmony_ci        if (_PyTuple_Resize(&parameters, iparam) < 0) {
2627db96d56Sopenharmony_ci            Py_XDECREF(parameters);
2637db96d56Sopenharmony_ci            return NULL;
2647db96d56Sopenharmony_ci        }
2657db96d56Sopenharmony_ci    }
2667db96d56Sopenharmony_ci    return parameters;
2677db96d56Sopenharmony_ci}
2687db96d56Sopenharmony_ci
2697db96d56Sopenharmony_ci/* If obj is a generic alias, substitute type variables params
2707db96d56Sopenharmony_ci   with substitutions argitems.  For example, if obj is list[T],
2717db96d56Sopenharmony_ci   params is (T, S), and argitems is (str, int), return list[str].
2727db96d56Sopenharmony_ci   If obj doesn't have a __parameters__ attribute or that's not
2737db96d56Sopenharmony_ci   a non-empty tuple, return a new reference to obj. */
2747db96d56Sopenharmony_cistatic PyObject *
2757db96d56Sopenharmony_cisubs_tvars(PyObject *obj, PyObject *params,
2767db96d56Sopenharmony_ci           PyObject **argitems, Py_ssize_t nargs)
2777db96d56Sopenharmony_ci{
2787db96d56Sopenharmony_ci    PyObject *subparams;
2797db96d56Sopenharmony_ci    if (_PyObject_LookupAttr(obj, &_Py_ID(__parameters__), &subparams) < 0) {
2807db96d56Sopenharmony_ci        return NULL;
2817db96d56Sopenharmony_ci    }
2827db96d56Sopenharmony_ci    if (subparams && PyTuple_Check(subparams) && PyTuple_GET_SIZE(subparams)) {
2837db96d56Sopenharmony_ci        Py_ssize_t nparams = PyTuple_GET_SIZE(params);
2847db96d56Sopenharmony_ci        Py_ssize_t nsubargs = PyTuple_GET_SIZE(subparams);
2857db96d56Sopenharmony_ci        PyObject *subargs = PyTuple_New(nsubargs);
2867db96d56Sopenharmony_ci        if (subargs == NULL) {
2877db96d56Sopenharmony_ci            Py_DECREF(subparams);
2887db96d56Sopenharmony_ci            return NULL;
2897db96d56Sopenharmony_ci        }
2907db96d56Sopenharmony_ci        Py_ssize_t j = 0;
2917db96d56Sopenharmony_ci        for (Py_ssize_t i = 0; i < nsubargs; ++i) {
2927db96d56Sopenharmony_ci            PyObject *arg = PyTuple_GET_ITEM(subparams, i);
2937db96d56Sopenharmony_ci            Py_ssize_t iparam = tuple_index(params, nparams, arg);
2947db96d56Sopenharmony_ci            if (iparam >= 0) {
2957db96d56Sopenharmony_ci                PyObject *param = PyTuple_GET_ITEM(params, iparam);
2967db96d56Sopenharmony_ci                arg = argitems[iparam];
2977db96d56Sopenharmony_ci                if (Py_TYPE(param)->tp_iter && PyTuple_Check(arg)) {  // TypeVarTuple
2987db96d56Sopenharmony_ci                    j = tuple_extend(&subargs, j,
2997db96d56Sopenharmony_ci                                    &PyTuple_GET_ITEM(arg, 0),
3007db96d56Sopenharmony_ci                                    PyTuple_GET_SIZE(arg));
3017db96d56Sopenharmony_ci                    if (j < 0) {
3027db96d56Sopenharmony_ci                        return NULL;
3037db96d56Sopenharmony_ci                    }
3047db96d56Sopenharmony_ci                    continue;
3057db96d56Sopenharmony_ci                }
3067db96d56Sopenharmony_ci            }
3077db96d56Sopenharmony_ci            Py_INCREF(arg);
3087db96d56Sopenharmony_ci            PyTuple_SET_ITEM(subargs, j, arg);
3097db96d56Sopenharmony_ci            j++;
3107db96d56Sopenharmony_ci        }
3117db96d56Sopenharmony_ci        assert(j == PyTuple_GET_SIZE(subargs));
3127db96d56Sopenharmony_ci
3137db96d56Sopenharmony_ci        obj = PyObject_GetItem(obj, subargs);
3147db96d56Sopenharmony_ci
3157db96d56Sopenharmony_ci        Py_DECREF(subargs);
3167db96d56Sopenharmony_ci    }
3177db96d56Sopenharmony_ci    else {
3187db96d56Sopenharmony_ci        Py_INCREF(obj);
3197db96d56Sopenharmony_ci    }
3207db96d56Sopenharmony_ci    Py_XDECREF(subparams);
3217db96d56Sopenharmony_ci    return obj;
3227db96d56Sopenharmony_ci}
3237db96d56Sopenharmony_ci
3247db96d56Sopenharmony_cistatic int
3257db96d56Sopenharmony_ci_is_unpacked_typevartuple(PyObject *arg)
3267db96d56Sopenharmony_ci{
3277db96d56Sopenharmony_ci    PyObject *tmp;
3287db96d56Sopenharmony_ci    if (PyType_Check(arg)) { // TODO: Add test
3297db96d56Sopenharmony_ci        return 0;
3307db96d56Sopenharmony_ci    }
3317db96d56Sopenharmony_ci    int res = _PyObject_LookupAttr(arg, &_Py_ID(__typing_is_unpacked_typevartuple__), &tmp);
3327db96d56Sopenharmony_ci    if (res > 0) {
3337db96d56Sopenharmony_ci        res = PyObject_IsTrue(tmp);
3347db96d56Sopenharmony_ci        Py_DECREF(tmp);
3357db96d56Sopenharmony_ci    }
3367db96d56Sopenharmony_ci    return res;
3377db96d56Sopenharmony_ci}
3387db96d56Sopenharmony_ci
3397db96d56Sopenharmony_cistatic PyObject *
3407db96d56Sopenharmony_ci_unpacked_tuple_args(PyObject *arg)
3417db96d56Sopenharmony_ci{
3427db96d56Sopenharmony_ci    PyObject *result;
3437db96d56Sopenharmony_ci    assert(!PyType_Check(arg));
3447db96d56Sopenharmony_ci    // Fast path
3457db96d56Sopenharmony_ci    if (_PyGenericAlias_Check(arg) &&
3467db96d56Sopenharmony_ci            ((gaobject *)arg)->starred &&
3477db96d56Sopenharmony_ci            ((gaobject *)arg)->origin == (PyObject *)&PyTuple_Type)
3487db96d56Sopenharmony_ci    {
3497db96d56Sopenharmony_ci        result = ((gaobject *)arg)->args;
3507db96d56Sopenharmony_ci        Py_INCREF(result);
3517db96d56Sopenharmony_ci        return result;
3527db96d56Sopenharmony_ci    }
3537db96d56Sopenharmony_ci
3547db96d56Sopenharmony_ci    if (_PyObject_LookupAttr(arg, &_Py_ID(__typing_unpacked_tuple_args__), &result) > 0) {
3557db96d56Sopenharmony_ci        if (result == Py_None) {
3567db96d56Sopenharmony_ci            Py_DECREF(result);
3577db96d56Sopenharmony_ci            return NULL;
3587db96d56Sopenharmony_ci        }
3597db96d56Sopenharmony_ci        return result;
3607db96d56Sopenharmony_ci    }
3617db96d56Sopenharmony_ci    return NULL;
3627db96d56Sopenharmony_ci}
3637db96d56Sopenharmony_ci
3647db96d56Sopenharmony_cistatic PyObject *
3657db96d56Sopenharmony_ci_unpack_args(PyObject *item)
3667db96d56Sopenharmony_ci{
3677db96d56Sopenharmony_ci    PyObject *newargs = PyList_New(0);
3687db96d56Sopenharmony_ci    if (newargs == NULL) {
3697db96d56Sopenharmony_ci        return NULL;
3707db96d56Sopenharmony_ci    }
3717db96d56Sopenharmony_ci    int is_tuple = PyTuple_Check(item);
3727db96d56Sopenharmony_ci    Py_ssize_t nitems = is_tuple ? PyTuple_GET_SIZE(item) : 1;
3737db96d56Sopenharmony_ci    PyObject **argitems = is_tuple ? &PyTuple_GET_ITEM(item, 0) : &item;
3747db96d56Sopenharmony_ci    for (Py_ssize_t i = 0; i < nitems; i++) {
3757db96d56Sopenharmony_ci        item = argitems[i];
3767db96d56Sopenharmony_ci        if (!PyType_Check(item)) {
3777db96d56Sopenharmony_ci            PyObject *subargs = _unpacked_tuple_args(item);
3787db96d56Sopenharmony_ci            if (subargs != NULL &&
3797db96d56Sopenharmony_ci                PyTuple_Check(subargs) &&
3807db96d56Sopenharmony_ci                !(PyTuple_GET_SIZE(subargs) &&
3817db96d56Sopenharmony_ci                  PyTuple_GET_ITEM(subargs, PyTuple_GET_SIZE(subargs)-1) == Py_Ellipsis))
3827db96d56Sopenharmony_ci            {
3837db96d56Sopenharmony_ci                if (PyList_SetSlice(newargs, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, subargs) < 0) {
3847db96d56Sopenharmony_ci                    Py_DECREF(subargs);
3857db96d56Sopenharmony_ci                    Py_DECREF(newargs);
3867db96d56Sopenharmony_ci                    return NULL;
3877db96d56Sopenharmony_ci                }
3887db96d56Sopenharmony_ci                Py_DECREF(subargs);
3897db96d56Sopenharmony_ci                continue;
3907db96d56Sopenharmony_ci            }
3917db96d56Sopenharmony_ci            Py_XDECREF(subargs);
3927db96d56Sopenharmony_ci            if (PyErr_Occurred()) {
3937db96d56Sopenharmony_ci                Py_DECREF(newargs);
3947db96d56Sopenharmony_ci                return NULL;
3957db96d56Sopenharmony_ci            }
3967db96d56Sopenharmony_ci        }
3977db96d56Sopenharmony_ci        if (PyList_Append(newargs, item) < 0) {
3987db96d56Sopenharmony_ci            Py_DECREF(newargs);
3997db96d56Sopenharmony_ci            return NULL;
4007db96d56Sopenharmony_ci        }
4017db96d56Sopenharmony_ci    }
4027db96d56Sopenharmony_ci    Py_SETREF(newargs, PySequence_Tuple(newargs));
4037db96d56Sopenharmony_ci    return newargs;
4047db96d56Sopenharmony_ci}
4057db96d56Sopenharmony_ci
4067db96d56Sopenharmony_ciPyObject *
4077db96d56Sopenharmony_ci_Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObject *item)
4087db96d56Sopenharmony_ci{
4097db96d56Sopenharmony_ci    Py_ssize_t nparams = PyTuple_GET_SIZE(parameters);
4107db96d56Sopenharmony_ci    if (nparams == 0) {
4117db96d56Sopenharmony_ci        return PyErr_Format(PyExc_TypeError,
4127db96d56Sopenharmony_ci                            "%R is not a generic class",
4137db96d56Sopenharmony_ci                            self);
4147db96d56Sopenharmony_ci    }
4157db96d56Sopenharmony_ci    item = _unpack_args(item);
4167db96d56Sopenharmony_ci    for (Py_ssize_t i = 0; i < nparams; i++) {
4177db96d56Sopenharmony_ci        PyObject *param = PyTuple_GET_ITEM(parameters, i);
4187db96d56Sopenharmony_ci        PyObject *prepare, *tmp;
4197db96d56Sopenharmony_ci        if (_PyObject_LookupAttr(param, &_Py_ID(__typing_prepare_subst__), &prepare) < 0) {
4207db96d56Sopenharmony_ci            Py_DECREF(item);
4217db96d56Sopenharmony_ci            return NULL;
4227db96d56Sopenharmony_ci        }
4237db96d56Sopenharmony_ci        if (prepare && prepare != Py_None) {
4247db96d56Sopenharmony_ci            if (PyTuple_Check(item)) {
4257db96d56Sopenharmony_ci                tmp = PyObject_CallFunction(prepare, "OO", self, item);
4267db96d56Sopenharmony_ci            }
4277db96d56Sopenharmony_ci            else {
4287db96d56Sopenharmony_ci                tmp = PyObject_CallFunction(prepare, "O(O)", self, item);
4297db96d56Sopenharmony_ci            }
4307db96d56Sopenharmony_ci            Py_DECREF(prepare);
4317db96d56Sopenharmony_ci            Py_SETREF(item, tmp);
4327db96d56Sopenharmony_ci            if (item == NULL) {
4337db96d56Sopenharmony_ci                return NULL;
4347db96d56Sopenharmony_ci            }
4357db96d56Sopenharmony_ci        }
4367db96d56Sopenharmony_ci    }
4377db96d56Sopenharmony_ci    int is_tuple = PyTuple_Check(item);
4387db96d56Sopenharmony_ci    Py_ssize_t nitems = is_tuple ? PyTuple_GET_SIZE(item) : 1;
4397db96d56Sopenharmony_ci    PyObject **argitems = is_tuple ? &PyTuple_GET_ITEM(item, 0) : &item;
4407db96d56Sopenharmony_ci    if (nitems != nparams) {
4417db96d56Sopenharmony_ci        Py_DECREF(item);
4427db96d56Sopenharmony_ci        return PyErr_Format(PyExc_TypeError,
4437db96d56Sopenharmony_ci                            "Too %s arguments for %R; actual %zd, expected %zd",
4447db96d56Sopenharmony_ci                            nitems > nparams ? "many" : "few",
4457db96d56Sopenharmony_ci                            self, nitems, nparams);
4467db96d56Sopenharmony_ci    }
4477db96d56Sopenharmony_ci    /* Replace all type variables (specified by parameters)
4487db96d56Sopenharmony_ci       with corresponding values specified by argitems.
4497db96d56Sopenharmony_ci        t = list[T];          t[int]      -> newargs = [int]
4507db96d56Sopenharmony_ci        t = dict[str, T];     t[int]      -> newargs = [str, int]
4517db96d56Sopenharmony_ci        t = dict[T, list[S]]; t[str, int] -> newargs = [str, list[int]]
4527db96d56Sopenharmony_ci     */
4537db96d56Sopenharmony_ci    Py_ssize_t nargs = PyTuple_GET_SIZE(args);
4547db96d56Sopenharmony_ci    PyObject *newargs = PyTuple_New(nargs);
4557db96d56Sopenharmony_ci    if (newargs == NULL) {
4567db96d56Sopenharmony_ci        Py_DECREF(item);
4577db96d56Sopenharmony_ci        return NULL;
4587db96d56Sopenharmony_ci    }
4597db96d56Sopenharmony_ci    for (Py_ssize_t iarg = 0, jarg = 0; iarg < nargs; iarg++) {
4607db96d56Sopenharmony_ci        PyObject *arg = PyTuple_GET_ITEM(args, iarg);
4617db96d56Sopenharmony_ci        if (PyType_Check(arg)) {
4627db96d56Sopenharmony_ci            Py_INCREF(arg);
4637db96d56Sopenharmony_ci            PyTuple_SET_ITEM(newargs, jarg, arg);
4647db96d56Sopenharmony_ci            jarg++;
4657db96d56Sopenharmony_ci            continue;
4667db96d56Sopenharmony_ci        }
4677db96d56Sopenharmony_ci
4687db96d56Sopenharmony_ci        int unpack = _is_unpacked_typevartuple(arg);
4697db96d56Sopenharmony_ci        if (unpack < 0) {
4707db96d56Sopenharmony_ci            Py_DECREF(newargs);
4717db96d56Sopenharmony_ci            Py_DECREF(item);
4727db96d56Sopenharmony_ci            return NULL;
4737db96d56Sopenharmony_ci        }
4747db96d56Sopenharmony_ci        PyObject *subst;
4757db96d56Sopenharmony_ci        if (_PyObject_LookupAttr(arg, &_Py_ID(__typing_subst__), &subst) < 0) {
4767db96d56Sopenharmony_ci            Py_DECREF(newargs);
4777db96d56Sopenharmony_ci            Py_DECREF(item);
4787db96d56Sopenharmony_ci            return NULL;
4797db96d56Sopenharmony_ci        }
4807db96d56Sopenharmony_ci        if (subst) {
4817db96d56Sopenharmony_ci            Py_ssize_t iparam = tuple_index(parameters, nparams, arg);
4827db96d56Sopenharmony_ci            assert(iparam >= 0);
4837db96d56Sopenharmony_ci            arg = PyObject_CallOneArg(subst, argitems[iparam]);
4847db96d56Sopenharmony_ci            Py_DECREF(subst);
4857db96d56Sopenharmony_ci        }
4867db96d56Sopenharmony_ci        else {
4877db96d56Sopenharmony_ci            arg = subs_tvars(arg, parameters, argitems, nitems);
4887db96d56Sopenharmony_ci        }
4897db96d56Sopenharmony_ci        if (arg == NULL) {
4907db96d56Sopenharmony_ci            Py_DECREF(newargs);
4917db96d56Sopenharmony_ci            Py_DECREF(item);
4927db96d56Sopenharmony_ci            return NULL;
4937db96d56Sopenharmony_ci        }
4947db96d56Sopenharmony_ci        if (unpack) {
4957db96d56Sopenharmony_ci            jarg = tuple_extend(&newargs, jarg,
4967db96d56Sopenharmony_ci                    &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg));
4977db96d56Sopenharmony_ci            Py_DECREF(arg);
4987db96d56Sopenharmony_ci            if (jarg < 0) {
4997db96d56Sopenharmony_ci                Py_DECREF(item);
5007db96d56Sopenharmony_ci                return NULL;
5017db96d56Sopenharmony_ci            }
5027db96d56Sopenharmony_ci        }
5037db96d56Sopenharmony_ci        else {
5047db96d56Sopenharmony_ci            PyTuple_SET_ITEM(newargs, jarg, arg);
5057db96d56Sopenharmony_ci            jarg++;
5067db96d56Sopenharmony_ci        }
5077db96d56Sopenharmony_ci    }
5087db96d56Sopenharmony_ci
5097db96d56Sopenharmony_ci    Py_DECREF(item);
5107db96d56Sopenharmony_ci    return newargs;
5117db96d56Sopenharmony_ci}
5127db96d56Sopenharmony_ci
5137db96d56Sopenharmony_ciPyDoc_STRVAR(genericalias__doc__,
5147db96d56Sopenharmony_ci"Represent a PEP 585 generic type\n"
5157db96d56Sopenharmony_ci"\n"
5167db96d56Sopenharmony_ci"E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).");
5177db96d56Sopenharmony_ci
5187db96d56Sopenharmony_cistatic PyObject *
5197db96d56Sopenharmony_ciga_getitem(PyObject *self, PyObject *item)
5207db96d56Sopenharmony_ci{
5217db96d56Sopenharmony_ci    gaobject *alias = (gaobject *)self;
5227db96d56Sopenharmony_ci    // Populate __parameters__ if needed.
5237db96d56Sopenharmony_ci    if (alias->parameters == NULL) {
5247db96d56Sopenharmony_ci        alias->parameters = _Py_make_parameters(alias->args);
5257db96d56Sopenharmony_ci        if (alias->parameters == NULL) {
5267db96d56Sopenharmony_ci            return NULL;
5277db96d56Sopenharmony_ci        }
5287db96d56Sopenharmony_ci    }
5297db96d56Sopenharmony_ci
5307db96d56Sopenharmony_ci    PyObject *newargs = _Py_subs_parameters(self, alias->args, alias->parameters, item);
5317db96d56Sopenharmony_ci    if (newargs == NULL) {
5327db96d56Sopenharmony_ci        return NULL;
5337db96d56Sopenharmony_ci    }
5347db96d56Sopenharmony_ci
5357db96d56Sopenharmony_ci    PyObject *res = Py_GenericAlias(alias->origin, newargs);
5367db96d56Sopenharmony_ci    ((gaobject *)res)->starred = alias->starred;
5377db96d56Sopenharmony_ci
5387db96d56Sopenharmony_ci    Py_DECREF(newargs);
5397db96d56Sopenharmony_ci    return res;
5407db96d56Sopenharmony_ci}
5417db96d56Sopenharmony_ci
5427db96d56Sopenharmony_cistatic PyMappingMethods ga_as_mapping = {
5437db96d56Sopenharmony_ci    .mp_subscript = ga_getitem,
5447db96d56Sopenharmony_ci};
5457db96d56Sopenharmony_ci
5467db96d56Sopenharmony_cistatic Py_hash_t
5477db96d56Sopenharmony_ciga_hash(PyObject *self)
5487db96d56Sopenharmony_ci{
5497db96d56Sopenharmony_ci    gaobject *alias = (gaobject *)self;
5507db96d56Sopenharmony_ci    // TODO: Hash in the hash for the origin
5517db96d56Sopenharmony_ci    Py_hash_t h0 = PyObject_Hash(alias->origin);
5527db96d56Sopenharmony_ci    if (h0 == -1) {
5537db96d56Sopenharmony_ci        return -1;
5547db96d56Sopenharmony_ci    }
5557db96d56Sopenharmony_ci    Py_hash_t h1 = PyObject_Hash(alias->args);
5567db96d56Sopenharmony_ci    if (h1 == -1) {
5577db96d56Sopenharmony_ci        return -1;
5587db96d56Sopenharmony_ci    }
5597db96d56Sopenharmony_ci    return h0 ^ h1;
5607db96d56Sopenharmony_ci}
5617db96d56Sopenharmony_ci
5627db96d56Sopenharmony_cistatic inline PyObject *
5637db96d56Sopenharmony_ciset_orig_class(PyObject *obj, PyObject *self)
5647db96d56Sopenharmony_ci{
5657db96d56Sopenharmony_ci    if (obj != NULL) {
5667db96d56Sopenharmony_ci        if (PyObject_SetAttr(obj, &_Py_ID(__orig_class__), self) < 0) {
5677db96d56Sopenharmony_ci            if (!PyErr_ExceptionMatches(PyExc_AttributeError) &&
5687db96d56Sopenharmony_ci                !PyErr_ExceptionMatches(PyExc_TypeError))
5697db96d56Sopenharmony_ci            {
5707db96d56Sopenharmony_ci                Py_DECREF(obj);
5717db96d56Sopenharmony_ci                return NULL;
5727db96d56Sopenharmony_ci            }
5737db96d56Sopenharmony_ci            PyErr_Clear();
5747db96d56Sopenharmony_ci        }
5757db96d56Sopenharmony_ci    }
5767db96d56Sopenharmony_ci    return obj;
5777db96d56Sopenharmony_ci}
5787db96d56Sopenharmony_ci
5797db96d56Sopenharmony_cistatic PyObject *
5807db96d56Sopenharmony_ciga_call(PyObject *self, PyObject *args, PyObject *kwds)
5817db96d56Sopenharmony_ci{
5827db96d56Sopenharmony_ci    gaobject *alias = (gaobject *)self;
5837db96d56Sopenharmony_ci    PyObject *obj = PyObject_Call(alias->origin, args, kwds);
5847db96d56Sopenharmony_ci    return set_orig_class(obj, self);
5857db96d56Sopenharmony_ci}
5867db96d56Sopenharmony_ci
5877db96d56Sopenharmony_cistatic PyObject *
5887db96d56Sopenharmony_ciga_vectorcall(PyObject *self, PyObject *const *args,
5897db96d56Sopenharmony_ci              size_t nargsf, PyObject *kwnames)
5907db96d56Sopenharmony_ci{
5917db96d56Sopenharmony_ci    gaobject *alias = (gaobject *) self;
5927db96d56Sopenharmony_ci    PyObject *obj = PyVectorcall_Function(alias->origin)(alias->origin, args, nargsf, kwnames);
5937db96d56Sopenharmony_ci    return set_orig_class(obj, self);
5947db96d56Sopenharmony_ci}
5957db96d56Sopenharmony_ci
5967db96d56Sopenharmony_cistatic const char* const attr_exceptions[] = {
5977db96d56Sopenharmony_ci    "__class__",
5987db96d56Sopenharmony_ci    "__origin__",
5997db96d56Sopenharmony_ci    "__args__",
6007db96d56Sopenharmony_ci    "__unpacked__",
6017db96d56Sopenharmony_ci    "__parameters__",
6027db96d56Sopenharmony_ci    "__typing_unpacked_tuple_args__",
6037db96d56Sopenharmony_ci    "__mro_entries__",
6047db96d56Sopenharmony_ci    "__reduce_ex__",  // needed so we don't look up object.__reduce_ex__
6057db96d56Sopenharmony_ci    "__reduce__",
6067db96d56Sopenharmony_ci    "__copy__",
6077db96d56Sopenharmony_ci    "__deepcopy__",
6087db96d56Sopenharmony_ci    NULL,
6097db96d56Sopenharmony_ci};
6107db96d56Sopenharmony_ci
6117db96d56Sopenharmony_cistatic PyObject *
6127db96d56Sopenharmony_ciga_getattro(PyObject *self, PyObject *name)
6137db96d56Sopenharmony_ci{
6147db96d56Sopenharmony_ci    gaobject *alias = (gaobject *)self;
6157db96d56Sopenharmony_ci    if (PyUnicode_Check(name)) {
6167db96d56Sopenharmony_ci        for (const char * const *p = attr_exceptions; ; p++) {
6177db96d56Sopenharmony_ci            if (*p == NULL) {
6187db96d56Sopenharmony_ci                return PyObject_GetAttr(alias->origin, name);
6197db96d56Sopenharmony_ci            }
6207db96d56Sopenharmony_ci            if (_PyUnicode_EqualToASCIIString(name, *p)) {
6217db96d56Sopenharmony_ci                break;
6227db96d56Sopenharmony_ci            }
6237db96d56Sopenharmony_ci        }
6247db96d56Sopenharmony_ci    }
6257db96d56Sopenharmony_ci    return PyObject_GenericGetAttr(self, name);
6267db96d56Sopenharmony_ci}
6277db96d56Sopenharmony_ci
6287db96d56Sopenharmony_cistatic PyObject *
6297db96d56Sopenharmony_ciga_richcompare(PyObject *a, PyObject *b, int op)
6307db96d56Sopenharmony_ci{
6317db96d56Sopenharmony_ci    if (!_PyGenericAlias_Check(b) ||
6327db96d56Sopenharmony_ci        (op != Py_EQ && op != Py_NE))
6337db96d56Sopenharmony_ci    {
6347db96d56Sopenharmony_ci        Py_RETURN_NOTIMPLEMENTED;
6357db96d56Sopenharmony_ci    }
6367db96d56Sopenharmony_ci
6377db96d56Sopenharmony_ci    if (op == Py_NE) {
6387db96d56Sopenharmony_ci        PyObject *eq = ga_richcompare(a, b, Py_EQ);
6397db96d56Sopenharmony_ci        if (eq == NULL)
6407db96d56Sopenharmony_ci            return NULL;
6417db96d56Sopenharmony_ci        Py_DECREF(eq);
6427db96d56Sopenharmony_ci        if (eq == Py_True) {
6437db96d56Sopenharmony_ci            Py_RETURN_FALSE;
6447db96d56Sopenharmony_ci        }
6457db96d56Sopenharmony_ci        else {
6467db96d56Sopenharmony_ci            Py_RETURN_TRUE;
6477db96d56Sopenharmony_ci        }
6487db96d56Sopenharmony_ci    }
6497db96d56Sopenharmony_ci
6507db96d56Sopenharmony_ci    gaobject *aa = (gaobject *)a;
6517db96d56Sopenharmony_ci    gaobject *bb = (gaobject *)b;
6527db96d56Sopenharmony_ci    if (aa->starred != bb->starred) {
6537db96d56Sopenharmony_ci        Py_RETURN_FALSE;
6547db96d56Sopenharmony_ci    }
6557db96d56Sopenharmony_ci    int eq = PyObject_RichCompareBool(aa->origin, bb->origin, Py_EQ);
6567db96d56Sopenharmony_ci    if (eq < 0) {
6577db96d56Sopenharmony_ci        return NULL;
6587db96d56Sopenharmony_ci    }
6597db96d56Sopenharmony_ci    if (!eq) {
6607db96d56Sopenharmony_ci        Py_RETURN_FALSE;
6617db96d56Sopenharmony_ci    }
6627db96d56Sopenharmony_ci    return PyObject_RichCompare(aa->args, bb->args, Py_EQ);
6637db96d56Sopenharmony_ci}
6647db96d56Sopenharmony_ci
6657db96d56Sopenharmony_cistatic PyObject *
6667db96d56Sopenharmony_ciga_mro_entries(PyObject *self, PyObject *args)
6677db96d56Sopenharmony_ci{
6687db96d56Sopenharmony_ci    gaobject *alias = (gaobject *)self;
6697db96d56Sopenharmony_ci    return PyTuple_Pack(1, alias->origin);
6707db96d56Sopenharmony_ci}
6717db96d56Sopenharmony_ci
6727db96d56Sopenharmony_cistatic PyObject *
6737db96d56Sopenharmony_ciga_instancecheck(PyObject *self, PyObject *Py_UNUSED(ignored))
6747db96d56Sopenharmony_ci{
6757db96d56Sopenharmony_ci    PyErr_SetString(PyExc_TypeError,
6767db96d56Sopenharmony_ci                    "isinstance() argument 2 cannot be a parameterized generic");
6777db96d56Sopenharmony_ci    return NULL;
6787db96d56Sopenharmony_ci}
6797db96d56Sopenharmony_ci
6807db96d56Sopenharmony_cistatic PyObject *
6817db96d56Sopenharmony_ciga_subclasscheck(PyObject *self, PyObject *Py_UNUSED(ignored))
6827db96d56Sopenharmony_ci{
6837db96d56Sopenharmony_ci    PyErr_SetString(PyExc_TypeError,
6847db96d56Sopenharmony_ci                    "issubclass() argument 2 cannot be a parameterized generic");
6857db96d56Sopenharmony_ci    return NULL;
6867db96d56Sopenharmony_ci}
6877db96d56Sopenharmony_ci
6887db96d56Sopenharmony_cistatic PyObject *
6897db96d56Sopenharmony_ciga_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
6907db96d56Sopenharmony_ci{
6917db96d56Sopenharmony_ci    gaobject *alias = (gaobject *)self;
6927db96d56Sopenharmony_ci    if (alias->starred) {
6937db96d56Sopenharmony_ci        PyObject *tmp = Py_GenericAlias(alias->origin, alias->args);
6947db96d56Sopenharmony_ci        if (tmp != NULL) {
6957db96d56Sopenharmony_ci            Py_SETREF(tmp, PyObject_GetIter(tmp));
6967db96d56Sopenharmony_ci        }
6977db96d56Sopenharmony_ci        if (tmp == NULL) {
6987db96d56Sopenharmony_ci            return NULL;
6997db96d56Sopenharmony_ci        }
7007db96d56Sopenharmony_ci        return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(next)), tmp);
7017db96d56Sopenharmony_ci    }
7027db96d56Sopenharmony_ci    return Py_BuildValue("O(OO)", Py_TYPE(alias),
7037db96d56Sopenharmony_ci                         alias->origin, alias->args);
7047db96d56Sopenharmony_ci}
7057db96d56Sopenharmony_ci
7067db96d56Sopenharmony_cistatic PyObject *
7077db96d56Sopenharmony_ciga_dir(PyObject *self, PyObject *Py_UNUSED(ignored))
7087db96d56Sopenharmony_ci{
7097db96d56Sopenharmony_ci    gaobject *alias = (gaobject *)self;
7107db96d56Sopenharmony_ci    PyObject *dir = PyObject_Dir(alias->origin);
7117db96d56Sopenharmony_ci    if (dir == NULL) {
7127db96d56Sopenharmony_ci        return NULL;
7137db96d56Sopenharmony_ci    }
7147db96d56Sopenharmony_ci
7157db96d56Sopenharmony_ci    PyObject *dir_entry = NULL;
7167db96d56Sopenharmony_ci    for (const char * const *p = attr_exceptions; ; p++) {
7177db96d56Sopenharmony_ci        if (*p == NULL) {
7187db96d56Sopenharmony_ci            break;
7197db96d56Sopenharmony_ci        }
7207db96d56Sopenharmony_ci        else {
7217db96d56Sopenharmony_ci            dir_entry = PyUnicode_FromString(*p);
7227db96d56Sopenharmony_ci            if (dir_entry == NULL) {
7237db96d56Sopenharmony_ci                goto error;
7247db96d56Sopenharmony_ci            }
7257db96d56Sopenharmony_ci            int contains = PySequence_Contains(dir, dir_entry);
7267db96d56Sopenharmony_ci            if (contains < 0) {
7277db96d56Sopenharmony_ci                goto error;
7287db96d56Sopenharmony_ci            }
7297db96d56Sopenharmony_ci            if (contains == 0 && PyList_Append(dir, dir_entry) < 0) {
7307db96d56Sopenharmony_ci                goto error;
7317db96d56Sopenharmony_ci            }
7327db96d56Sopenharmony_ci
7337db96d56Sopenharmony_ci            Py_CLEAR(dir_entry);
7347db96d56Sopenharmony_ci        }
7357db96d56Sopenharmony_ci    }
7367db96d56Sopenharmony_ci    return dir;
7377db96d56Sopenharmony_ci
7387db96d56Sopenharmony_cierror:
7397db96d56Sopenharmony_ci    Py_DECREF(dir);
7407db96d56Sopenharmony_ci    Py_XDECREF(dir_entry);
7417db96d56Sopenharmony_ci    return NULL;
7427db96d56Sopenharmony_ci}
7437db96d56Sopenharmony_ci
7447db96d56Sopenharmony_cistatic PyMethodDef ga_methods[] = {
7457db96d56Sopenharmony_ci    {"__mro_entries__", ga_mro_entries, METH_O},
7467db96d56Sopenharmony_ci    {"__instancecheck__", ga_instancecheck, METH_O},
7477db96d56Sopenharmony_ci    {"__subclasscheck__", ga_subclasscheck, METH_O},
7487db96d56Sopenharmony_ci    {"__reduce__", ga_reduce, METH_NOARGS},
7497db96d56Sopenharmony_ci    {"__dir__", ga_dir, METH_NOARGS},
7507db96d56Sopenharmony_ci    {0}
7517db96d56Sopenharmony_ci};
7527db96d56Sopenharmony_ci
7537db96d56Sopenharmony_cistatic PyMemberDef ga_members[] = {
7547db96d56Sopenharmony_ci    {"__origin__", T_OBJECT, offsetof(gaobject, origin), READONLY},
7557db96d56Sopenharmony_ci    {"__args__", T_OBJECT, offsetof(gaobject, args), READONLY},
7567db96d56Sopenharmony_ci    {"__unpacked__", T_BOOL, offsetof(gaobject, starred), READONLY},
7577db96d56Sopenharmony_ci    {0}
7587db96d56Sopenharmony_ci};
7597db96d56Sopenharmony_ci
7607db96d56Sopenharmony_cistatic PyObject *
7617db96d56Sopenharmony_ciga_parameters(PyObject *self, void *unused)
7627db96d56Sopenharmony_ci{
7637db96d56Sopenharmony_ci    gaobject *alias = (gaobject *)self;
7647db96d56Sopenharmony_ci    if (alias->parameters == NULL) {
7657db96d56Sopenharmony_ci        alias->parameters = _Py_make_parameters(alias->args);
7667db96d56Sopenharmony_ci        if (alias->parameters == NULL) {
7677db96d56Sopenharmony_ci            return NULL;
7687db96d56Sopenharmony_ci        }
7697db96d56Sopenharmony_ci    }
7707db96d56Sopenharmony_ci    Py_INCREF(alias->parameters);
7717db96d56Sopenharmony_ci    return alias->parameters;
7727db96d56Sopenharmony_ci}
7737db96d56Sopenharmony_ci
7747db96d56Sopenharmony_cistatic PyObject *
7757db96d56Sopenharmony_ciga_unpacked_tuple_args(PyObject *self, void *unused)
7767db96d56Sopenharmony_ci{
7777db96d56Sopenharmony_ci    gaobject *alias = (gaobject *)self;
7787db96d56Sopenharmony_ci    if (alias->starred && alias->origin == (PyObject *)&PyTuple_Type) {
7797db96d56Sopenharmony_ci        Py_INCREF(alias->args);
7807db96d56Sopenharmony_ci        return alias->args;
7817db96d56Sopenharmony_ci    }
7827db96d56Sopenharmony_ci    Py_RETURN_NONE;
7837db96d56Sopenharmony_ci}
7847db96d56Sopenharmony_ci
7857db96d56Sopenharmony_cistatic PyGetSetDef ga_properties[] = {
7867db96d56Sopenharmony_ci    {"__parameters__", ga_parameters, (setter)NULL, "Type variables in the GenericAlias.", NULL},
7877db96d56Sopenharmony_ci    {"__typing_unpacked_tuple_args__", ga_unpacked_tuple_args, (setter)NULL, NULL},
7887db96d56Sopenharmony_ci    {0}
7897db96d56Sopenharmony_ci};
7907db96d56Sopenharmony_ci
7917db96d56Sopenharmony_ci/* A helper function to create GenericAlias' args tuple and set its attributes.
7927db96d56Sopenharmony_ci * Returns 1 on success, 0 on failure.
7937db96d56Sopenharmony_ci */
7947db96d56Sopenharmony_cistatic inline int
7957db96d56Sopenharmony_cisetup_ga(gaobject *alias, PyObject *origin, PyObject *args) {
7967db96d56Sopenharmony_ci    if (!PyTuple_Check(args)) {
7977db96d56Sopenharmony_ci        args = PyTuple_Pack(1, args);
7987db96d56Sopenharmony_ci        if (args == NULL) {
7997db96d56Sopenharmony_ci            return 0;
8007db96d56Sopenharmony_ci        }
8017db96d56Sopenharmony_ci    }
8027db96d56Sopenharmony_ci    else {
8037db96d56Sopenharmony_ci        Py_INCREF(args);
8047db96d56Sopenharmony_ci    }
8057db96d56Sopenharmony_ci
8067db96d56Sopenharmony_ci    Py_INCREF(origin);
8077db96d56Sopenharmony_ci    alias->origin = origin;
8087db96d56Sopenharmony_ci    alias->args = args;
8097db96d56Sopenharmony_ci    alias->parameters = NULL;
8107db96d56Sopenharmony_ci    alias->weakreflist = NULL;
8117db96d56Sopenharmony_ci
8127db96d56Sopenharmony_ci    if (PyVectorcall_Function(origin) != NULL) {
8137db96d56Sopenharmony_ci        alias->vectorcall = ga_vectorcall;
8147db96d56Sopenharmony_ci    }
8157db96d56Sopenharmony_ci    else {
8167db96d56Sopenharmony_ci        alias->vectorcall = NULL;
8177db96d56Sopenharmony_ci    }
8187db96d56Sopenharmony_ci
8197db96d56Sopenharmony_ci    return 1;
8207db96d56Sopenharmony_ci}
8217db96d56Sopenharmony_ci
8227db96d56Sopenharmony_cistatic PyObject *
8237db96d56Sopenharmony_ciga_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
8247db96d56Sopenharmony_ci{
8257db96d56Sopenharmony_ci    if (!_PyArg_NoKeywords("GenericAlias", kwds)) {
8267db96d56Sopenharmony_ci        return NULL;
8277db96d56Sopenharmony_ci    }
8287db96d56Sopenharmony_ci    if (!_PyArg_CheckPositional("GenericAlias", PyTuple_GET_SIZE(args), 2, 2)) {
8297db96d56Sopenharmony_ci        return NULL;
8307db96d56Sopenharmony_ci    }
8317db96d56Sopenharmony_ci    PyObject *origin = PyTuple_GET_ITEM(args, 0);
8327db96d56Sopenharmony_ci    PyObject *arguments = PyTuple_GET_ITEM(args, 1);
8337db96d56Sopenharmony_ci    gaobject *self = (gaobject *)type->tp_alloc(type, 0);
8347db96d56Sopenharmony_ci    if (self == NULL) {
8357db96d56Sopenharmony_ci        return NULL;
8367db96d56Sopenharmony_ci    }
8377db96d56Sopenharmony_ci    if (!setup_ga(self, origin, arguments)) {
8387db96d56Sopenharmony_ci        Py_DECREF(self);
8397db96d56Sopenharmony_ci        return NULL;
8407db96d56Sopenharmony_ci    }
8417db96d56Sopenharmony_ci    return (PyObject *)self;
8427db96d56Sopenharmony_ci}
8437db96d56Sopenharmony_ci
8447db96d56Sopenharmony_cistatic PyNumberMethods ga_as_number = {
8457db96d56Sopenharmony_ci        .nb_or = _Py_union_type_or, // Add __or__ function
8467db96d56Sopenharmony_ci};
8477db96d56Sopenharmony_ci
8487db96d56Sopenharmony_cistatic PyObject *
8497db96d56Sopenharmony_ciga_iternext(gaiterobject *gi) {
8507db96d56Sopenharmony_ci    if (gi->obj == NULL) {
8517db96d56Sopenharmony_ci        PyErr_SetNone(PyExc_StopIteration);
8527db96d56Sopenharmony_ci        return NULL;
8537db96d56Sopenharmony_ci    }
8547db96d56Sopenharmony_ci    gaobject *alias = (gaobject *)gi->obj;
8557db96d56Sopenharmony_ci    PyObject *starred_alias = Py_GenericAlias(alias->origin, alias->args);
8567db96d56Sopenharmony_ci    if (starred_alias == NULL) {
8577db96d56Sopenharmony_ci        return NULL;
8587db96d56Sopenharmony_ci    }
8597db96d56Sopenharmony_ci    ((gaobject *)starred_alias)->starred = true;
8607db96d56Sopenharmony_ci    Py_SETREF(gi->obj, NULL);
8617db96d56Sopenharmony_ci    return starred_alias;
8627db96d56Sopenharmony_ci}
8637db96d56Sopenharmony_ci
8647db96d56Sopenharmony_cistatic void
8657db96d56Sopenharmony_ciga_iter_dealloc(gaiterobject *gi) {
8667db96d56Sopenharmony_ci    PyObject_GC_UnTrack(gi);
8677db96d56Sopenharmony_ci    Py_XDECREF(gi->obj);
8687db96d56Sopenharmony_ci    PyObject_GC_Del(gi);
8697db96d56Sopenharmony_ci}
8707db96d56Sopenharmony_ci
8717db96d56Sopenharmony_cistatic int
8727db96d56Sopenharmony_ciga_iter_traverse(gaiterobject *gi, visitproc visit, void *arg)
8737db96d56Sopenharmony_ci{
8747db96d56Sopenharmony_ci    Py_VISIT(gi->obj);
8757db96d56Sopenharmony_ci    return 0;
8767db96d56Sopenharmony_ci}
8777db96d56Sopenharmony_ci
8787db96d56Sopenharmony_cistatic int
8797db96d56Sopenharmony_ciga_iter_clear(PyObject *self) {
8807db96d56Sopenharmony_ci    gaiterobject *gi = (gaiterobject *)self;
8817db96d56Sopenharmony_ci    Py_CLEAR(gi->obj);
8827db96d56Sopenharmony_ci    return 0;
8837db96d56Sopenharmony_ci}
8847db96d56Sopenharmony_ci
8857db96d56Sopenharmony_cistatic PyObject *
8867db96d56Sopenharmony_ciga_iter_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
8877db96d56Sopenharmony_ci{
8887db96d56Sopenharmony_ci    PyObject *iter = _PyEval_GetBuiltin(&_Py_ID(iter));
8897db96d56Sopenharmony_ci    gaiterobject *gi = (gaiterobject *)self;
8907db96d56Sopenharmony_ci
8917db96d56Sopenharmony_ci    /* _PyEval_GetBuiltin can invoke arbitrary code,
8927db96d56Sopenharmony_ci     * call must be before access of iterator pointers.
8937db96d56Sopenharmony_ci     * see issue #101765 */
8947db96d56Sopenharmony_ci
8957db96d56Sopenharmony_ci    if (gi->obj)
8967db96d56Sopenharmony_ci        return Py_BuildValue("N(O)", iter, gi->obj);
8977db96d56Sopenharmony_ci    else
8987db96d56Sopenharmony_ci        return Py_BuildValue("N(())", iter);
8997db96d56Sopenharmony_ci}
9007db96d56Sopenharmony_ci
9017db96d56Sopenharmony_cistatic PyMethodDef ga_iter_methods[] = {
9027db96d56Sopenharmony_ci    {"__reduce__", ga_iter_reduce, METH_NOARGS},
9037db96d56Sopenharmony_ci    {0}
9047db96d56Sopenharmony_ci};
9057db96d56Sopenharmony_ci
9067db96d56Sopenharmony_ci// gh-91632: _Py_GenericAliasIterType is exported  to be cleared
9077db96d56Sopenharmony_ci// in _PyTypes_FiniTypes.
9087db96d56Sopenharmony_ciPyTypeObject _Py_GenericAliasIterType = {
9097db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
9107db96d56Sopenharmony_ci    .tp_name = "generic_alias_iterator",
9117db96d56Sopenharmony_ci    .tp_basicsize = sizeof(gaiterobject),
9127db96d56Sopenharmony_ci    .tp_iter = PyObject_SelfIter,
9137db96d56Sopenharmony_ci    .tp_iternext = (iternextfunc)ga_iternext,
9147db96d56Sopenharmony_ci    .tp_traverse = (traverseproc)ga_iter_traverse,
9157db96d56Sopenharmony_ci    .tp_methods = ga_iter_methods,
9167db96d56Sopenharmony_ci    .tp_dealloc = (destructor)ga_iter_dealloc,
9177db96d56Sopenharmony_ci    .tp_clear = (inquiry)ga_iter_clear,
9187db96d56Sopenharmony_ci    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
9197db96d56Sopenharmony_ci};
9207db96d56Sopenharmony_ci
9217db96d56Sopenharmony_cistatic PyObject *
9227db96d56Sopenharmony_ciga_iter(PyObject *self) {
9237db96d56Sopenharmony_ci    gaiterobject *gi = PyObject_GC_New(gaiterobject, &_Py_GenericAliasIterType);
9247db96d56Sopenharmony_ci    if (gi == NULL) {
9257db96d56Sopenharmony_ci        return NULL;
9267db96d56Sopenharmony_ci    }
9277db96d56Sopenharmony_ci    gi->obj = Py_NewRef(self);
9287db96d56Sopenharmony_ci    PyObject_GC_Track(gi);
9297db96d56Sopenharmony_ci    return (PyObject *)gi;
9307db96d56Sopenharmony_ci}
9317db96d56Sopenharmony_ci
9327db96d56Sopenharmony_ci// TODO:
9337db96d56Sopenharmony_ci// - argument clinic?
9347db96d56Sopenharmony_ci// - cache?
9357db96d56Sopenharmony_ciPyTypeObject Py_GenericAliasType = {
9367db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
9377db96d56Sopenharmony_ci    .tp_name = "types.GenericAlias",
9387db96d56Sopenharmony_ci    .tp_doc = genericalias__doc__,
9397db96d56Sopenharmony_ci    .tp_basicsize = sizeof(gaobject),
9407db96d56Sopenharmony_ci    .tp_dealloc = ga_dealloc,
9417db96d56Sopenharmony_ci    .tp_repr = ga_repr,
9427db96d56Sopenharmony_ci    .tp_as_number = &ga_as_number,  // allow X | Y of GenericAlias objs
9437db96d56Sopenharmony_ci    .tp_as_mapping = &ga_as_mapping,
9447db96d56Sopenharmony_ci    .tp_hash = ga_hash,
9457db96d56Sopenharmony_ci    .tp_call = ga_call,
9467db96d56Sopenharmony_ci    .tp_getattro = ga_getattro,
9477db96d56Sopenharmony_ci    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_VECTORCALL,
9487db96d56Sopenharmony_ci    .tp_traverse = ga_traverse,
9497db96d56Sopenharmony_ci    .tp_richcompare = ga_richcompare,
9507db96d56Sopenharmony_ci    .tp_weaklistoffset = offsetof(gaobject, weakreflist),
9517db96d56Sopenharmony_ci    .tp_methods = ga_methods,
9527db96d56Sopenharmony_ci    .tp_members = ga_members,
9537db96d56Sopenharmony_ci    .tp_alloc = PyType_GenericAlloc,
9547db96d56Sopenharmony_ci    .tp_new = ga_new,
9557db96d56Sopenharmony_ci    .tp_free = PyObject_GC_Del,
9567db96d56Sopenharmony_ci    .tp_getset = ga_properties,
9577db96d56Sopenharmony_ci    .tp_iter = (getiterfunc)ga_iter,
9587db96d56Sopenharmony_ci    .tp_vectorcall_offset = offsetof(gaobject, vectorcall),
9597db96d56Sopenharmony_ci};
9607db96d56Sopenharmony_ci
9617db96d56Sopenharmony_ciPyObject *
9627db96d56Sopenharmony_ciPy_GenericAlias(PyObject *origin, PyObject *args)
9637db96d56Sopenharmony_ci{
9647db96d56Sopenharmony_ci    gaobject *alias = (gaobject*) PyType_GenericAlloc(
9657db96d56Sopenharmony_ci            (PyTypeObject *)&Py_GenericAliasType, 0);
9667db96d56Sopenharmony_ci    if (alias == NULL) {
9677db96d56Sopenharmony_ci        return NULL;
9687db96d56Sopenharmony_ci    }
9697db96d56Sopenharmony_ci    if (!setup_ga(alias, origin, args)) {
9707db96d56Sopenharmony_ci        Py_DECREF(alias);
9717db96d56Sopenharmony_ci        return NULL;
9727db96d56Sopenharmony_ci    }
9737db96d56Sopenharmony_ci    return (PyObject *)alias;
9747db96d56Sopenharmony_ci}
975