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(¶meters, 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(¶meters, 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