• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // types.GenericAlias -- used to represent e.g. list[int].
2 
3 #include "Python.h"
4 #include "pycore_ceval.h"         // _PyEval_GetBuiltin()
5 #include "pycore_modsupport.h"    // _PyArg_NoKeywords()
6 #include "pycore_object.h"
7 #include "pycore_unionobject.h"   // _Py_union_type_or, _PyGenericAlias_Check
8 
9 
10 #include <stdbool.h>
11 
12 typedef struct {
13     PyObject_HEAD
14     PyObject *origin;
15     PyObject *args;
16     PyObject *parameters;
17     PyObject *weakreflist;
18     // Whether we're a starred type, e.g. *tuple[int].
19     bool starred;
20     vectorcallfunc vectorcall;
21 } gaobject;
22 
23 typedef struct {
24     PyObject_HEAD
25     PyObject *obj;  /* Set to NULL when iterator is exhausted */
26 } gaiterobject;
27 
28 static void
ga_dealloc(PyObject * self)29 ga_dealloc(PyObject *self)
30 {
31     gaobject *alias = (gaobject *)self;
32 
33     _PyObject_GC_UNTRACK(self);
34     if (alias->weakreflist != NULL) {
35         PyObject_ClearWeakRefs((PyObject *)alias);
36     }
37     Py_XDECREF(alias->origin);
38     Py_XDECREF(alias->args);
39     Py_XDECREF(alias->parameters);
40     Py_TYPE(self)->tp_free(self);
41 }
42 
43 static int
ga_traverse(PyObject * self,visitproc visit,void * arg)44 ga_traverse(PyObject *self, visitproc visit, void *arg)
45 {
46     gaobject *alias = (gaobject *)self;
47     Py_VISIT(alias->origin);
48     Py_VISIT(alias->args);
49     Py_VISIT(alias->parameters);
50     return 0;
51 }
52 
53 static int
ga_repr_item(_PyUnicodeWriter * writer,PyObject * p)54 ga_repr_item(_PyUnicodeWriter *writer, PyObject *p)
55 {
56     PyObject *qualname = NULL;
57     PyObject *module = NULL;
58     PyObject *r = NULL;
59     int rc;
60 
61     if (p == Py_Ellipsis) {
62         // The Ellipsis object
63         r = PyUnicode_FromString("...");
64         goto done;
65     }
66 
67     if ((rc = PyObject_HasAttrWithError(p, &_Py_ID(__origin__))) > 0 &&
68         (rc = PyObject_HasAttrWithError(p, &_Py_ID(__args__))) > 0)
69     {
70         // It looks like a GenericAlias
71         goto use_repr;
72     }
73     if (rc < 0) {
74         goto done;
75     }
76 
77     if (PyObject_GetOptionalAttr(p, &_Py_ID(__qualname__), &qualname) < 0) {
78         goto done;
79     }
80     if (qualname == NULL) {
81         goto use_repr;
82     }
83     if (PyObject_GetOptionalAttr(p, &_Py_ID(__module__), &module) < 0) {
84         goto done;
85     }
86     if (module == NULL || module == Py_None) {
87         goto use_repr;
88     }
89 
90     // Looks like a class
91     if (PyUnicode_Check(module) &&
92         _PyUnicode_EqualToASCIIString(module, "builtins"))
93     {
94         // builtins don't need a module name
95         r = PyObject_Str(qualname);
96         goto done;
97     }
98     else {
99         r = PyUnicode_FromFormat("%S.%S", module, qualname);
100         goto done;
101     }
102 
103 use_repr:
104     r = PyObject_Repr(p);
105 
106 done:
107     Py_XDECREF(qualname);
108     Py_XDECREF(module);
109     if (r == NULL) {
110         // error if any of the above PyObject_Repr/PyUnicode_From* fail
111         rc = -1;
112     }
113     else {
114         rc = _PyUnicodeWriter_WriteStr(writer, r);
115         Py_DECREF(r);
116     }
117     return rc;
118 }
119 
120 static int
ga_repr_items_list(_PyUnicodeWriter * writer,PyObject * p)121 ga_repr_items_list(_PyUnicodeWriter *writer, PyObject *p)
122 {
123     assert(PyList_CheckExact(p));
124 
125     Py_ssize_t len = PyList_GET_SIZE(p);
126 
127     if (_PyUnicodeWriter_WriteASCIIString(writer, "[", 1) < 0) {
128         return -1;
129     }
130 
131     for (Py_ssize_t i = 0; i < len; i++) {
132         if (i > 0) {
133             if (_PyUnicodeWriter_WriteASCIIString(writer, ", ", 2) < 0) {
134                 return -1;
135             }
136         }
137         PyObject *item = PyList_GET_ITEM(p, i);
138         if (ga_repr_item(writer, item) < 0) {
139             return -1;
140         }
141     }
142 
143     if (_PyUnicodeWriter_WriteASCIIString(writer, "]", 1) < 0) {
144         return -1;
145     }
146 
147     return 0;
148 }
149 
150 static PyObject *
ga_repr(PyObject * self)151 ga_repr(PyObject *self)
152 {
153     gaobject *alias = (gaobject *)self;
154     Py_ssize_t len = PyTuple_GET_SIZE(alias->args);
155 
156     _PyUnicodeWriter writer;
157     _PyUnicodeWriter_Init(&writer);
158 
159     if (alias->starred) {
160         if (_PyUnicodeWriter_WriteASCIIString(&writer, "*", 1) < 0) {
161             goto error;
162         }
163     }
164     if (ga_repr_item(&writer, alias->origin) < 0) {
165         goto error;
166     }
167     if (_PyUnicodeWriter_WriteASCIIString(&writer, "[", 1) < 0) {
168         goto error;
169     }
170     for (Py_ssize_t i = 0; i < len; i++) {
171         if (i > 0) {
172             if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) {
173                 goto error;
174             }
175         }
176         PyObject *p = PyTuple_GET_ITEM(alias->args, i);
177         if (PyList_CheckExact(p)) {
178             // Looks like we are working with ParamSpec's list of type args:
179             if (ga_repr_items_list(&writer, p) < 0) {
180                 goto error;
181             }
182         }
183         else if (ga_repr_item(&writer, p) < 0) {
184             goto error;
185         }
186     }
187     if (len == 0) {
188         // for something like tuple[()] we should print a "()"
189         if (_PyUnicodeWriter_WriteASCIIString(&writer, "()", 2) < 0) {
190             goto error;
191         }
192     }
193     if (_PyUnicodeWriter_WriteASCIIString(&writer, "]", 1) < 0) {
194         goto error;
195     }
196     return _PyUnicodeWriter_Finish(&writer);
197 error:
198     _PyUnicodeWriter_Dealloc(&writer);
199     return NULL;
200 }
201 
202 // Index of item in self[:len], or -1 if not found (self is a tuple)
203 static Py_ssize_t
tuple_index(PyObject * self,Py_ssize_t len,PyObject * item)204 tuple_index(PyObject *self, Py_ssize_t len, PyObject *item)
205 {
206     for (Py_ssize_t i = 0; i < len; i++) {
207         if (PyTuple_GET_ITEM(self, i) == item) {
208             return i;
209         }
210     }
211     return -1;
212 }
213 
214 static int
tuple_add(PyObject * self,Py_ssize_t len,PyObject * item)215 tuple_add(PyObject *self, Py_ssize_t len, PyObject *item)
216 {
217     if (tuple_index(self, len, item) < 0) {
218         PyTuple_SET_ITEM(self, len, Py_NewRef(item));
219         return 1;
220     }
221     return 0;
222 }
223 
224 static Py_ssize_t
tuple_extend(PyObject ** dst,Py_ssize_t dstindex,PyObject ** src,Py_ssize_t count)225 tuple_extend(PyObject **dst, Py_ssize_t dstindex,
226              PyObject **src, Py_ssize_t count)
227 {
228     assert(count >= 0);
229     if (_PyTuple_Resize(dst, PyTuple_GET_SIZE(*dst) + count - 1) != 0) {
230         return -1;
231     }
232     assert(dstindex + count <= PyTuple_GET_SIZE(*dst));
233     for (Py_ssize_t i = 0; i < count; ++i) {
234         PyObject *item = src[i];
235         PyTuple_SET_ITEM(*dst, dstindex + i, Py_NewRef(item));
236     }
237     return dstindex + count;
238 }
239 
240 PyObject *
_Py_make_parameters(PyObject * args)241 _Py_make_parameters(PyObject *args)
242 {
243     Py_ssize_t nargs = PyTuple_GET_SIZE(args);
244     Py_ssize_t len = nargs;
245     PyObject *parameters = PyTuple_New(len);
246     if (parameters == NULL)
247         return NULL;
248     Py_ssize_t iparam = 0;
249     for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
250         PyObject *t = PyTuple_GET_ITEM(args, iarg);
251         // We don't want __parameters__ descriptor of a bare Python class.
252         if (PyType_Check(t)) {
253             continue;
254         }
255         int rc = PyObject_HasAttrWithError(t, &_Py_ID(__typing_subst__));
256         if (rc < 0) {
257             Py_DECREF(parameters);
258             return NULL;
259         }
260         if (rc) {
261             iparam += tuple_add(parameters, iparam, t);
262         }
263         else {
264             PyObject *subparams;
265             if (PyObject_GetOptionalAttr(t, &_Py_ID(__parameters__),
266                                      &subparams) < 0) {
267                 Py_DECREF(parameters);
268                 return NULL;
269             }
270             if (subparams && PyTuple_Check(subparams)) {
271                 Py_ssize_t len2 = PyTuple_GET_SIZE(subparams);
272                 Py_ssize_t needed = len2 - 1 - (iarg - iparam);
273                 if (needed > 0) {
274                     len += needed;
275                     if (_PyTuple_Resize(&parameters, len) < 0) {
276                         Py_DECREF(subparams);
277                         Py_DECREF(parameters);
278                         return NULL;
279                     }
280                 }
281                 for (Py_ssize_t j = 0; j < len2; j++) {
282                     PyObject *t2 = PyTuple_GET_ITEM(subparams, j);
283                     iparam += tuple_add(parameters, iparam, t2);
284                 }
285             }
286             Py_XDECREF(subparams);
287         }
288     }
289     if (iparam < len) {
290         if (_PyTuple_Resize(&parameters, iparam) < 0) {
291             Py_XDECREF(parameters);
292             return NULL;
293         }
294     }
295     return parameters;
296 }
297 
298 /* If obj is a generic alias, substitute type variables params
299    with substitutions argitems.  For example, if obj is list[T],
300    params is (T, S), and argitems is (str, int), return list[str].
301    If obj doesn't have a __parameters__ attribute or that's not
302    a non-empty tuple, return a new reference to obj. */
303 static PyObject *
subs_tvars(PyObject * obj,PyObject * params,PyObject ** argitems,Py_ssize_t nargs)304 subs_tvars(PyObject *obj, PyObject *params,
305            PyObject **argitems, Py_ssize_t nargs)
306 {
307     PyObject *subparams;
308     if (PyObject_GetOptionalAttr(obj, &_Py_ID(__parameters__), &subparams) < 0) {
309         return NULL;
310     }
311     if (subparams && PyTuple_Check(subparams) && PyTuple_GET_SIZE(subparams)) {
312         Py_ssize_t nparams = PyTuple_GET_SIZE(params);
313         Py_ssize_t nsubargs = PyTuple_GET_SIZE(subparams);
314         PyObject *subargs = PyTuple_New(nsubargs);
315         if (subargs == NULL) {
316             Py_DECREF(subparams);
317             return NULL;
318         }
319         Py_ssize_t j = 0;
320         for (Py_ssize_t i = 0; i < nsubargs; ++i) {
321             PyObject *arg = PyTuple_GET_ITEM(subparams, i);
322             Py_ssize_t iparam = tuple_index(params, nparams, arg);
323             if (iparam >= 0) {
324                 PyObject *param = PyTuple_GET_ITEM(params, iparam);
325                 arg = argitems[iparam];
326                 if (Py_TYPE(param)->tp_iter && PyTuple_Check(arg)) {  // TypeVarTuple
327                     j = tuple_extend(&subargs, j,
328                                     &PyTuple_GET_ITEM(arg, 0),
329                                     PyTuple_GET_SIZE(arg));
330                     if (j < 0) {
331                         return NULL;
332                     }
333                     continue;
334                 }
335             }
336             PyTuple_SET_ITEM(subargs, j, Py_NewRef(arg));
337             j++;
338         }
339         assert(j == PyTuple_GET_SIZE(subargs));
340 
341         obj = PyObject_GetItem(obj, subargs);
342 
343         Py_DECREF(subargs);
344     }
345     else {
346         Py_INCREF(obj);
347     }
348     Py_XDECREF(subparams);
349     return obj;
350 }
351 
352 static int
_is_unpacked_typevartuple(PyObject * arg)353 _is_unpacked_typevartuple(PyObject *arg)
354 {
355     PyObject *tmp;
356     if (PyType_Check(arg)) { // TODO: Add test
357         return 0;
358     }
359     int res = PyObject_GetOptionalAttr(arg, &_Py_ID(__typing_is_unpacked_typevartuple__), &tmp);
360     if (res > 0) {
361         res = PyObject_IsTrue(tmp);
362         Py_DECREF(tmp);
363     }
364     return res;
365 }
366 
367 static PyObject *
_unpacked_tuple_args(PyObject * arg)368 _unpacked_tuple_args(PyObject *arg)
369 {
370     PyObject *result;
371     assert(!PyType_Check(arg));
372     // Fast path
373     if (_PyGenericAlias_Check(arg) &&
374             ((gaobject *)arg)->starred &&
375             ((gaobject *)arg)->origin == (PyObject *)&PyTuple_Type)
376     {
377         result = ((gaobject *)arg)->args;
378         return Py_NewRef(result);
379     }
380 
381     if (PyObject_GetOptionalAttr(arg, &_Py_ID(__typing_unpacked_tuple_args__), &result) > 0) {
382         if (result == Py_None) {
383             Py_DECREF(result);
384             return NULL;
385         }
386         return result;
387     }
388     return NULL;
389 }
390 
391 static PyObject *
_unpack_args(PyObject * item)392 _unpack_args(PyObject *item)
393 {
394     PyObject *newargs = PyList_New(0);
395     if (newargs == NULL) {
396         return NULL;
397     }
398     int is_tuple = PyTuple_Check(item);
399     Py_ssize_t nitems = is_tuple ? PyTuple_GET_SIZE(item) : 1;
400     PyObject **argitems = is_tuple ? &PyTuple_GET_ITEM(item, 0) : &item;
401     for (Py_ssize_t i = 0; i < nitems; i++) {
402         item = argitems[i];
403         if (!PyType_Check(item)) {
404             PyObject *subargs = _unpacked_tuple_args(item);
405             if (subargs != NULL &&
406                 PyTuple_Check(subargs) &&
407                 !(PyTuple_GET_SIZE(subargs) &&
408                   PyTuple_GET_ITEM(subargs, PyTuple_GET_SIZE(subargs)-1) == Py_Ellipsis))
409             {
410                 if (PyList_SetSlice(newargs, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, subargs) < 0) {
411                     Py_DECREF(subargs);
412                     Py_DECREF(newargs);
413                     return NULL;
414                 }
415                 Py_DECREF(subargs);
416                 continue;
417             }
418             Py_XDECREF(subargs);
419             if (PyErr_Occurred()) {
420                 Py_DECREF(newargs);
421                 return NULL;
422             }
423         }
424         if (PyList_Append(newargs, item) < 0) {
425             Py_DECREF(newargs);
426             return NULL;
427         }
428     }
429     Py_SETREF(newargs, PySequence_Tuple(newargs));
430     return newargs;
431 }
432 
433 PyObject *
_Py_subs_parameters(PyObject * self,PyObject * args,PyObject * parameters,PyObject * item)434 _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObject *item)
435 {
436     Py_ssize_t nparams = PyTuple_GET_SIZE(parameters);
437     if (nparams == 0) {
438         return PyErr_Format(PyExc_TypeError,
439                             "%R is not a generic class",
440                             self);
441     }
442     item = _unpack_args(item);
443     for (Py_ssize_t i = 0; i < nparams; i++) {
444         PyObject *param = PyTuple_GET_ITEM(parameters, i);
445         PyObject *prepare, *tmp;
446         if (PyObject_GetOptionalAttr(param, &_Py_ID(__typing_prepare_subst__), &prepare) < 0) {
447             Py_DECREF(item);
448             return NULL;
449         }
450         if (prepare && prepare != Py_None) {
451             if (PyTuple_Check(item)) {
452                 tmp = PyObject_CallFunction(prepare, "OO", self, item);
453             }
454             else {
455                 tmp = PyObject_CallFunction(prepare, "O(O)", self, item);
456             }
457             Py_DECREF(prepare);
458             Py_SETREF(item, tmp);
459             if (item == NULL) {
460                 return NULL;
461             }
462         }
463     }
464     int is_tuple = PyTuple_Check(item);
465     Py_ssize_t nitems = is_tuple ? PyTuple_GET_SIZE(item) : 1;
466     PyObject **argitems = is_tuple ? &PyTuple_GET_ITEM(item, 0) : &item;
467     if (nitems != nparams) {
468         Py_DECREF(item);
469         return PyErr_Format(PyExc_TypeError,
470                             "Too %s arguments for %R; actual %zd, expected %zd",
471                             nitems > nparams ? "many" : "few",
472                             self, nitems, nparams);
473     }
474     /* Replace all type variables (specified by parameters)
475        with corresponding values specified by argitems.
476         t = list[T];          t[int]      -> newargs = [int]
477         t = dict[str, T];     t[int]      -> newargs = [str, int]
478         t = dict[T, list[S]]; t[str, int] -> newargs = [str, list[int]]
479      */
480     Py_ssize_t nargs = PyTuple_GET_SIZE(args);
481     PyObject *newargs = PyTuple_New(nargs);
482     if (newargs == NULL) {
483         Py_DECREF(item);
484         return NULL;
485     }
486     for (Py_ssize_t iarg = 0, jarg = 0; iarg < nargs; iarg++) {
487         PyObject *arg = PyTuple_GET_ITEM(args, iarg);
488         if (PyType_Check(arg)) {
489             PyTuple_SET_ITEM(newargs, jarg, Py_NewRef(arg));
490             jarg++;
491             continue;
492         }
493 
494         int unpack = _is_unpacked_typevartuple(arg);
495         if (unpack < 0) {
496             Py_DECREF(newargs);
497             Py_DECREF(item);
498             return NULL;
499         }
500         PyObject *subst;
501         if (PyObject_GetOptionalAttr(arg, &_Py_ID(__typing_subst__), &subst) < 0) {
502             Py_DECREF(newargs);
503             Py_DECREF(item);
504             return NULL;
505         }
506         if (subst) {
507             Py_ssize_t iparam = tuple_index(parameters, nparams, arg);
508             assert(iparam >= 0);
509             arg = PyObject_CallOneArg(subst, argitems[iparam]);
510             Py_DECREF(subst);
511         }
512         else {
513             arg = subs_tvars(arg, parameters, argitems, nitems);
514         }
515         if (arg == NULL) {
516             Py_DECREF(newargs);
517             Py_DECREF(item);
518             return NULL;
519         }
520         if (unpack) {
521             jarg = tuple_extend(&newargs, jarg,
522                     &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg));
523             Py_DECREF(arg);
524             if (jarg < 0) {
525                 Py_DECREF(item);
526                 return NULL;
527             }
528         }
529         else {
530             PyTuple_SET_ITEM(newargs, jarg, arg);
531             jarg++;
532         }
533     }
534 
535     Py_DECREF(item);
536     return newargs;
537 }
538 
539 PyDoc_STRVAR(genericalias__doc__,
540 "GenericAlias(origin, args, /)\n"
541 "--\n\n"
542 "Represent a PEP 585 generic type\n"
543 "\n"
544 "E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).");
545 
546 static PyObject *
ga_getitem(PyObject * self,PyObject * item)547 ga_getitem(PyObject *self, PyObject *item)
548 {
549     gaobject *alias = (gaobject *)self;
550     // Populate __parameters__ if needed.
551     if (alias->parameters == NULL) {
552         alias->parameters = _Py_make_parameters(alias->args);
553         if (alias->parameters == NULL) {
554             return NULL;
555         }
556     }
557 
558     PyObject *newargs = _Py_subs_parameters(self, alias->args, alias->parameters, item);
559     if (newargs == NULL) {
560         return NULL;
561     }
562 
563     PyObject *res = Py_GenericAlias(alias->origin, newargs);
564     if (res == NULL) {
565         Py_DECREF(newargs);
566         return NULL;
567     }
568     ((gaobject *)res)->starred = alias->starred;
569 
570     Py_DECREF(newargs);
571     return res;
572 }
573 
574 static PyMappingMethods ga_as_mapping = {
575     .mp_subscript = ga_getitem,
576 };
577 
578 static Py_hash_t
ga_hash(PyObject * self)579 ga_hash(PyObject *self)
580 {
581     gaobject *alias = (gaobject *)self;
582     // TODO: Hash in the hash for the origin
583     Py_hash_t h0 = PyObject_Hash(alias->origin);
584     if (h0 == -1) {
585         return -1;
586     }
587     Py_hash_t h1 = PyObject_Hash(alias->args);
588     if (h1 == -1) {
589         return -1;
590     }
591     return h0 ^ h1;
592 }
593 
594 static inline PyObject *
set_orig_class(PyObject * obj,PyObject * self)595 set_orig_class(PyObject *obj, PyObject *self)
596 {
597     if (obj != NULL) {
598         if (PyObject_SetAttr(obj, &_Py_ID(__orig_class__), self) < 0) {
599             if (!PyErr_ExceptionMatches(PyExc_AttributeError) &&
600                 !PyErr_ExceptionMatches(PyExc_TypeError))
601             {
602                 Py_DECREF(obj);
603                 return NULL;
604             }
605             PyErr_Clear();
606         }
607     }
608     return obj;
609 }
610 
611 static PyObject *
ga_call(PyObject * self,PyObject * args,PyObject * kwds)612 ga_call(PyObject *self, PyObject *args, PyObject *kwds)
613 {
614     gaobject *alias = (gaobject *)self;
615     PyObject *obj = PyObject_Call(alias->origin, args, kwds);
616     return set_orig_class(obj, self);
617 }
618 
619 static PyObject *
ga_vectorcall(PyObject * self,PyObject * const * args,size_t nargsf,PyObject * kwnames)620 ga_vectorcall(PyObject *self, PyObject *const *args,
621               size_t nargsf, PyObject *kwnames)
622 {
623     gaobject *alias = (gaobject *) self;
624     PyObject *obj = PyVectorcall_Function(alias->origin)(alias->origin, args, nargsf, kwnames);
625     return set_orig_class(obj, self);
626 }
627 
628 static const char* const attr_exceptions[] = {
629     "__class__",
630     "__bases__",
631     "__origin__",
632     "__args__",
633     "__unpacked__",
634     "__parameters__",
635     "__typing_unpacked_tuple_args__",
636     "__mro_entries__",
637     "__reduce_ex__",  // needed so we don't look up object.__reduce_ex__
638     "__reduce__",
639     "__copy__",
640     "__deepcopy__",
641     NULL,
642 };
643 
644 static PyObject *
ga_getattro(PyObject * self,PyObject * name)645 ga_getattro(PyObject *self, PyObject *name)
646 {
647     gaobject *alias = (gaobject *)self;
648     if (PyUnicode_Check(name)) {
649         for (const char * const *p = attr_exceptions; ; p++) {
650             if (*p == NULL) {
651                 return PyObject_GetAttr(alias->origin, name);
652             }
653             if (_PyUnicode_EqualToASCIIString(name, *p)) {
654                 break;
655             }
656         }
657     }
658     return PyObject_GenericGetAttr(self, name);
659 }
660 
661 static PyObject *
ga_richcompare(PyObject * a,PyObject * b,int op)662 ga_richcompare(PyObject *a, PyObject *b, int op)
663 {
664     if (!_PyGenericAlias_Check(b) ||
665         (op != Py_EQ && op != Py_NE))
666     {
667         Py_RETURN_NOTIMPLEMENTED;
668     }
669 
670     if (op == Py_NE) {
671         PyObject *eq = ga_richcompare(a, b, Py_EQ);
672         if (eq == NULL)
673             return NULL;
674         Py_DECREF(eq);
675         if (eq == Py_True) {
676             Py_RETURN_FALSE;
677         }
678         else {
679             Py_RETURN_TRUE;
680         }
681     }
682 
683     gaobject *aa = (gaobject *)a;
684     gaobject *bb = (gaobject *)b;
685     if (aa->starred != bb->starred) {
686         Py_RETURN_FALSE;
687     }
688     int eq = PyObject_RichCompareBool(aa->origin, bb->origin, Py_EQ);
689     if (eq < 0) {
690         return NULL;
691     }
692     if (!eq) {
693         Py_RETURN_FALSE;
694     }
695     return PyObject_RichCompare(aa->args, bb->args, Py_EQ);
696 }
697 
698 static PyObject *
ga_mro_entries(PyObject * self,PyObject * args)699 ga_mro_entries(PyObject *self, PyObject *args)
700 {
701     gaobject *alias = (gaobject *)self;
702     return PyTuple_Pack(1, alias->origin);
703 }
704 
705 static PyObject *
ga_instancecheck(PyObject * self,PyObject * Py_UNUSED (ignored))706 ga_instancecheck(PyObject *self, PyObject *Py_UNUSED(ignored))
707 {
708     PyErr_SetString(PyExc_TypeError,
709                     "isinstance() argument 2 cannot be a parameterized generic");
710     return NULL;
711 }
712 
713 static PyObject *
ga_subclasscheck(PyObject * self,PyObject * Py_UNUSED (ignored))714 ga_subclasscheck(PyObject *self, PyObject *Py_UNUSED(ignored))
715 {
716     PyErr_SetString(PyExc_TypeError,
717                     "issubclass() argument 2 cannot be a parameterized generic");
718     return NULL;
719 }
720 
721 static PyObject *
ga_reduce(PyObject * self,PyObject * Py_UNUSED (ignored))722 ga_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
723 {
724     gaobject *alias = (gaobject *)self;
725     if (alias->starred) {
726         PyObject *tmp = Py_GenericAlias(alias->origin, alias->args);
727         if (tmp != NULL) {
728             Py_SETREF(tmp, PyObject_GetIter(tmp));
729         }
730         if (tmp == NULL) {
731             return NULL;
732         }
733         return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(next)), tmp);
734     }
735     return Py_BuildValue("O(OO)", Py_TYPE(alias),
736                          alias->origin, alias->args);
737 }
738 
739 static PyObject *
ga_dir(PyObject * self,PyObject * Py_UNUSED (ignored))740 ga_dir(PyObject *self, PyObject *Py_UNUSED(ignored))
741 {
742     gaobject *alias = (gaobject *)self;
743     PyObject *dir = PyObject_Dir(alias->origin);
744     if (dir == NULL) {
745         return NULL;
746     }
747 
748     PyObject *dir_entry = NULL;
749     for (const char * const *p = attr_exceptions; ; p++) {
750         if (*p == NULL) {
751             break;
752         }
753         else {
754             dir_entry = PyUnicode_FromString(*p);
755             if (dir_entry == NULL) {
756                 goto error;
757             }
758             int contains = PySequence_Contains(dir, dir_entry);
759             if (contains < 0) {
760                 goto error;
761             }
762             if (contains == 0 && PyList_Append(dir, dir_entry) < 0) {
763                 goto error;
764             }
765 
766             Py_CLEAR(dir_entry);
767         }
768     }
769     return dir;
770 
771 error:
772     Py_DECREF(dir);
773     Py_XDECREF(dir_entry);
774     return NULL;
775 }
776 
777 static PyMethodDef ga_methods[] = {
778     {"__mro_entries__", ga_mro_entries, METH_O},
779     {"__instancecheck__", ga_instancecheck, METH_O},
780     {"__subclasscheck__", ga_subclasscheck, METH_O},
781     {"__reduce__", ga_reduce, METH_NOARGS},
782     {"__dir__", ga_dir, METH_NOARGS},
783     {0}
784 };
785 
786 static PyMemberDef ga_members[] = {
787     {"__origin__", _Py_T_OBJECT, offsetof(gaobject, origin), Py_READONLY},
788     {"__args__", _Py_T_OBJECT, offsetof(gaobject, args), Py_READONLY},
789     {"__unpacked__", Py_T_BOOL, offsetof(gaobject, starred), Py_READONLY},
790     {0}
791 };
792 
793 static PyObject *
ga_parameters(PyObject * self,void * unused)794 ga_parameters(PyObject *self, void *unused)
795 {
796     gaobject *alias = (gaobject *)self;
797     if (alias->parameters == NULL) {
798         alias->parameters = _Py_make_parameters(alias->args);
799         if (alias->parameters == NULL) {
800             return NULL;
801         }
802     }
803     return Py_NewRef(alias->parameters);
804 }
805 
806 static PyObject *
ga_unpacked_tuple_args(PyObject * self,void * unused)807 ga_unpacked_tuple_args(PyObject *self, void *unused)
808 {
809     gaobject *alias = (gaobject *)self;
810     if (alias->starred && alias->origin == (PyObject *)&PyTuple_Type) {
811         return Py_NewRef(alias->args);
812     }
813     Py_RETURN_NONE;
814 }
815 
816 static PyGetSetDef ga_properties[] = {
817     {"__parameters__", ga_parameters, (setter)NULL, PyDoc_STR("Type variables in the GenericAlias."), NULL},
818     {"__typing_unpacked_tuple_args__", ga_unpacked_tuple_args, (setter)NULL, NULL},
819     {0}
820 };
821 
822 /* A helper function to create GenericAlias' args tuple and set its attributes.
823  * Returns 1 on success, 0 on failure.
824  */
825 static inline int
setup_ga(gaobject * alias,PyObject * origin,PyObject * args)826 setup_ga(gaobject *alias, PyObject *origin, PyObject *args) {
827     if (!PyTuple_Check(args)) {
828         args = PyTuple_Pack(1, args);
829         if (args == NULL) {
830             return 0;
831         }
832     }
833     else {
834         Py_INCREF(args);
835     }
836 
837     alias->origin = Py_NewRef(origin);
838     alias->args = args;
839     alias->parameters = NULL;
840     alias->weakreflist = NULL;
841 
842     if (PyVectorcall_Function(origin) != NULL) {
843         alias->vectorcall = ga_vectorcall;
844     }
845     else {
846         alias->vectorcall = NULL;
847     }
848 
849     return 1;
850 }
851 
852 static PyObject *
ga_new(PyTypeObject * type,PyObject * args,PyObject * kwds)853 ga_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
854 {
855     if (!_PyArg_NoKeywords("GenericAlias", kwds)) {
856         return NULL;
857     }
858     if (!_PyArg_CheckPositional("GenericAlias", PyTuple_GET_SIZE(args), 2, 2)) {
859         return NULL;
860     }
861     PyObject *origin = PyTuple_GET_ITEM(args, 0);
862     PyObject *arguments = PyTuple_GET_ITEM(args, 1);
863     gaobject *self = (gaobject *)type->tp_alloc(type, 0);
864     if (self == NULL) {
865         return NULL;
866     }
867     if (!setup_ga(self, origin, arguments)) {
868         Py_DECREF(self);
869         return NULL;
870     }
871     return (PyObject *)self;
872 }
873 
874 static PyNumberMethods ga_as_number = {
875         .nb_or = _Py_union_type_or, // Add __or__ function
876 };
877 
878 static PyObject *
ga_iternext(gaiterobject * gi)879 ga_iternext(gaiterobject *gi) {
880     if (gi->obj == NULL) {
881         PyErr_SetNone(PyExc_StopIteration);
882         return NULL;
883     }
884     gaobject *alias = (gaobject *)gi->obj;
885     PyObject *starred_alias = Py_GenericAlias(alias->origin, alias->args);
886     if (starred_alias == NULL) {
887         return NULL;
888     }
889     ((gaobject *)starred_alias)->starred = true;
890     Py_SETREF(gi->obj, NULL);
891     return starred_alias;
892 }
893 
894 static void
ga_iter_dealloc(gaiterobject * gi)895 ga_iter_dealloc(gaiterobject *gi) {
896     PyObject_GC_UnTrack(gi);
897     Py_XDECREF(gi->obj);
898     PyObject_GC_Del(gi);
899 }
900 
901 static int
ga_iter_traverse(gaiterobject * gi,visitproc visit,void * arg)902 ga_iter_traverse(gaiterobject *gi, visitproc visit, void *arg)
903 {
904     Py_VISIT(gi->obj);
905     return 0;
906 }
907 
908 static int
ga_iter_clear(PyObject * self)909 ga_iter_clear(PyObject *self) {
910     gaiterobject *gi = (gaiterobject *)self;
911     Py_CLEAR(gi->obj);
912     return 0;
913 }
914 
915 static PyObject *
ga_iter_reduce(PyObject * self,PyObject * Py_UNUSED (ignored))916 ga_iter_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
917 {
918     PyObject *iter = _PyEval_GetBuiltin(&_Py_ID(iter));
919     gaiterobject *gi = (gaiterobject *)self;
920 
921     /* _PyEval_GetBuiltin can invoke arbitrary code,
922      * call must be before access of iterator pointers.
923      * see issue #101765 */
924 
925     if (gi->obj)
926         return Py_BuildValue("N(O)", iter, gi->obj);
927     else
928         return Py_BuildValue("N(())", iter);
929 }
930 
931 static PyMethodDef ga_iter_methods[] = {
932     {"__reduce__", ga_iter_reduce, METH_NOARGS},
933     {0}
934 };
935 
936 // gh-91632: _Py_GenericAliasIterType is exported  to be cleared
937 // in _PyTypes_FiniTypes.
938 PyTypeObject _Py_GenericAliasIterType = {
939     PyVarObject_HEAD_INIT(&PyType_Type, 0)
940     .tp_name = "generic_alias_iterator",
941     .tp_basicsize = sizeof(gaiterobject),
942     .tp_iter = PyObject_SelfIter,
943     .tp_iternext = (iternextfunc)ga_iternext,
944     .tp_traverse = (traverseproc)ga_iter_traverse,
945     .tp_methods = ga_iter_methods,
946     .tp_dealloc = (destructor)ga_iter_dealloc,
947     .tp_clear = (inquiry)ga_iter_clear,
948     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
949 };
950 
951 static PyObject *
ga_iter(PyObject * self)952 ga_iter(PyObject *self) {
953     gaiterobject *gi = PyObject_GC_New(gaiterobject, &_Py_GenericAliasIterType);
954     if (gi == NULL) {
955         return NULL;
956     }
957     gi->obj = Py_NewRef(self);
958     PyObject_GC_Track(gi);
959     return (PyObject *)gi;
960 }
961 
962 // TODO:
963 // - argument clinic?
964 // - cache?
965 PyTypeObject Py_GenericAliasType = {
966     PyVarObject_HEAD_INIT(&PyType_Type, 0)
967     .tp_name = "types.GenericAlias",
968     .tp_doc = genericalias__doc__,
969     .tp_basicsize = sizeof(gaobject),
970     .tp_dealloc = ga_dealloc,
971     .tp_repr = ga_repr,
972     .tp_as_number = &ga_as_number,  // allow X | Y of GenericAlias objs
973     .tp_as_mapping = &ga_as_mapping,
974     .tp_hash = ga_hash,
975     .tp_call = ga_call,
976     .tp_getattro = ga_getattro,
977     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_VECTORCALL,
978     .tp_traverse = ga_traverse,
979     .tp_richcompare = ga_richcompare,
980     .tp_weaklistoffset = offsetof(gaobject, weakreflist),
981     .tp_methods = ga_methods,
982     .tp_members = ga_members,
983     .tp_alloc = PyType_GenericAlloc,
984     .tp_new = ga_new,
985     .tp_free = PyObject_GC_Del,
986     .tp_getset = ga_properties,
987     .tp_iter = (getiterfunc)ga_iter,
988     .tp_vectorcall_offset = offsetof(gaobject, vectorcall),
989 };
990 
991 PyObject *
Py_GenericAlias(PyObject * origin,PyObject * args)992 Py_GenericAlias(PyObject *origin, PyObject *args)
993 {
994     gaobject *alias = (gaobject*) PyType_GenericAlloc(
995             (PyTypeObject *)&Py_GenericAliasType, 0);
996     if (alias == NULL) {
997         return NULL;
998     }
999     if (!setup_ga(alias, origin, args)) {
1000         Py_DECREF(alias);
1001         return NULL;
1002     }
1003     return (PyObject *)alias;
1004 }
1005