@@ -1799,6 +1799,24 @@ _Py_make_typevartuple(PyThreadState *Py_UNUSED(ignored), PyObject *v)
17991799 return (PyObject * )typevartuple_alloc (v , NULL , NULL );
18001800}
18011801
1802+ static PyObject *
1803+ get_type_param_default (PyThreadState * ts , PyObject * typeparam ) {
1804+ // Does not modify refcount of existing objects.
1805+ if (Py_IS_TYPE (typeparam , ts -> interp -> cached_objects .typevar_type )) {
1806+ return typevar_default ((typevarobject * )typeparam , NULL );
1807+ }
1808+ else if (Py_IS_TYPE (typeparam , ts -> interp -> cached_objects .paramspec_type )) {
1809+ return paramspec_default ((paramspecobject * )typeparam , NULL );
1810+ }
1811+ else if (Py_IS_TYPE (typeparam , ts -> interp -> cached_objects .typevartuple_type )) {
1812+ return typevartuple_default ((typevartupleobject * )typeparam , NULL );
1813+ }
1814+ else {
1815+ PyErr_Format (PyExc_TypeError , "Expected a type param, got %R" , typeparam );
1816+ return NULL ;
1817+ }
1818+ }
1819+
18021820static void
18031821typealias_dealloc (PyObject * self )
18041822{
@@ -1906,25 +1924,75 @@ static PyGetSetDef typealias_getset[] = {
19061924 {0 }
19071925};
19081926
1909- static typealiasobject *
1910- typealias_alloc (PyObject * name , PyObject * type_params , PyObject * compute_value ,
1911- PyObject * value , PyObject * module )
1912- {
1913- typealiasobject * ta = PyObject_GC_New (typealiasobject , & _PyTypeAlias_Type );
1914- if (ta == NULL ) {
1927+ static PyObject *
1928+ typealias_check_type_params (PyObject * type_params , int * err ) {
1929+ // Can return type_params or NULL without exception set.
1930+ // Does not change the reference count of type_params,
1931+ // sets `*err` to 1 when error happens and sets an exception,
1932+ // otherwise `*err` is set to 0.
1933+ * err = 0 ;
1934+ if (type_params == NULL ) {
19151935 return NULL ;
19161936 }
1917- ta -> name = Py_NewRef (name );
1937+
1938+ assert (PyTuple_Check (type_params ));
1939+ Py_ssize_t length = PyTuple_GET_SIZE (type_params );
1940+ if (!length ) { // 0-length tuples are the same as `NULL`.
1941+ return NULL ;
1942+ }
1943+
1944+ PyThreadState * ts = _PyThreadState_GET ();
1945+ int default_seen = 0 ;
1946+ for (Py_ssize_t index = 0 ; index < length ; index ++ ) {
1947+ PyObject * type_param = PyTuple_GET_ITEM (type_params , index );
1948+ PyObject * dflt = get_type_param_default (ts , type_param );
1949+ if (dflt == NULL ) {
1950+ * err = 1 ;
1951+ return NULL ;
1952+ }
1953+ if (dflt == & _Py_NoDefaultStruct ) {
1954+ if (default_seen ) {
1955+ * err = 1 ;
1956+ PyErr_Format (PyExc_TypeError ,
1957+ "non-default type parameter '%R' "
1958+ "follows default type parameter" ,
1959+ type_param );
1960+ return NULL ;
1961+ }
1962+ } else {
1963+ default_seen = 1 ;
1964+ Py_DECREF (dflt );
1965+ }
1966+ }
1967+
1968+ return type_params ;
1969+ }
1970+
1971+ static PyObject *
1972+ typelias_convert_type_params (PyObject * type_params )
1973+ {
19181974 if (
19191975 type_params == NULL
19201976 || Py_IsNone (type_params )
19211977 || (PyTuple_Check (type_params ) && PyTuple_GET_SIZE (type_params ) == 0 )
19221978 ) {
1923- ta -> type_params = NULL ;
1979+ return NULL ;
19241980 }
19251981 else {
1926- ta -> type_params = Py_NewRef ( type_params ) ;
1982+ return type_params ;
19271983 }
1984+ }
1985+
1986+ static typealiasobject *
1987+ typealias_alloc (PyObject * name , PyObject * type_params , PyObject * compute_value ,
1988+ PyObject * value , PyObject * module )
1989+ {
1990+ typealiasobject * ta = PyObject_GC_New (typealiasobject , & _PyTypeAlias_Type );
1991+ if (ta == NULL ) {
1992+ return NULL ;
1993+ }
1994+ ta -> name = Py_NewRef (name );
1995+ ta -> type_params = Py_XNewRef (type_params );
19281996 ta -> compute_value = Py_XNewRef (compute_value );
19291997 ta -> value = Py_XNewRef (value );
19301998 ta -> module = Py_XNewRef (module );
@@ -2002,11 +2070,18 @@ typealias_new_impl(PyTypeObject *type, PyObject *name, PyObject *value,
20022070 PyErr_SetString (PyExc_TypeError , "type_params must be a tuple" );
20032071 return NULL ;
20042072 }
2073+
2074+ int err = 0 ;
2075+ PyObject * checked_params = typealias_check_type_params (type_params , & err );
2076+ if (err ) {
2077+ return NULL ;
2078+ }
2079+
20052080 PyObject * module = caller ();
20062081 if (module == NULL ) {
20072082 return NULL ;
20082083 }
2009- PyObject * ta = (PyObject * )typealias_alloc (name , type_params , NULL , value ,
2084+ PyObject * ta = (PyObject * )typealias_alloc (name , checked_params , NULL , value ,
20102085 module );
20112086 Py_DECREF (module );
20122087 return ta ;
@@ -2072,7 +2147,7 @@ _Py_make_typealias(PyThreadState* unused, PyObject *args)
20722147 assert (PyTuple_GET_SIZE (args ) == 3 );
20732148 PyObject * name = PyTuple_GET_ITEM (args , 0 );
20742149 assert (PyUnicode_Check (name ));
2075- PyObject * type_params = PyTuple_GET_ITEM (args , 1 );
2150+ PyObject * type_params = typelias_convert_type_params ( PyTuple_GET_ITEM (args , 1 ) );
20762151 PyObject * compute_value = PyTuple_GET_ITEM (args , 2 );
20772152 assert (PyFunction_Check (compute_value ));
20782153 return (PyObject * )typealias_alloc (name , type_params , compute_value , NULL , NULL );
0 commit comments