summaryrefslogtreecommitdiff
path: root/Cython/Compiler/PyrexTypes.py
diff options
context:
space:
mode:
Diffstat (limited to 'Cython/Compiler/PyrexTypes.py')
-rw-r--r--Cython/Compiler/PyrexTypes.py68
1 files changed, 20 insertions, 48 deletions
diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py
index c773f5c5a..79e144ed1 100644
--- a/Cython/Compiler/PyrexTypes.py
+++ b/Cython/Compiler/PyrexTypes.py
@@ -205,6 +205,7 @@ class PyrexType(BaseType):
# needs_cpp_construction boolean Needs C++ constructor and destructor when used in a cdef class
# needs_refcounting boolean Needs code to be generated similar to incref/gotref/decref.
# Largely used internally.
+ # equivalent_type type A C or Python type that is equivalent to this Python or C type.
# default_value string Initial value that can be assigned before first user assignment.
# declaration_value string The value statically assigned on declaration (if any).
# entry Entry The Entry for this type
@@ -277,6 +278,7 @@ class PyrexType(BaseType):
has_attributes = 0
needs_cpp_construction = 0
needs_refcounting = 0
+ equivalent_type = None
default_value = ""
declaration_value = ""
@@ -1504,7 +1506,6 @@ class PyExtensionType(PyObjectType):
#
# name string
# scope CClassScope Attribute namespace
- # visibility string
# typedef_flag boolean
# base_type PyExtensionType or None
# module_name string or None Qualified name of defining module
@@ -1518,6 +1519,7 @@ class PyExtensionType(PyObjectType):
# vtable_cname string Name of C method table definition
# early_init boolean Whether to initialize early (as opposed to during module execution).
# defered_declarations [thunk] Used to declare class hierarchies in order
+ # is_external boolean Defined in a extern block
# check_size 'warn', 'error', 'ignore' What to do if tp_basicsize does not match
# dataclass_fields OrderedDict nor None Used for inheriting from dataclasses
@@ -3044,6 +3046,9 @@ class CFuncType(CType):
# must catch C++ exceptions if we raise them
return 0
if not other_type.exception_check or other_type.exception_value is not None:
+ # There's no problem if this type doesn't emit exceptions but the other type checks
+ if other_type.exception_check and not (self.exception_check or self.exception_value):
+ return 1
# if other does not *always* check exceptions, self must comply
if not self._same_exception_value(other_type.exception_value):
return 0
@@ -4429,6 +4434,7 @@ class ErrorType(PyrexType):
class PythonTypeConstructor(PyObjectType):
"""Used to help Cython interpret indexed types from the typing module (or similar)
"""
+ modifier_name = None
def __init__(self, name, base_type=None):
self.python_type_constructor_name = name
@@ -4457,69 +4463,35 @@ class PythonTupleTypeConstructor(PythonTypeConstructor):
not any(v.is_pyobject for v in template_values)):
entry = env.declare_tuple_type(pos, template_values)
if entry:
+ entry.used = True
return entry.type
return super(PythonTupleTypeConstructor, self).specialize_here(pos, env, template_values)
class SpecialPythonTypeConstructor(PythonTypeConstructor):
"""
- For things like ClassVar, Optional, etc, which have extra features on top of being
- a "templated" type.
+ For things like ClassVar, Optional, etc, which are not types and disappear during type analysis.
"""
- def __init__(self, name, template_type=None):
- super(SpecialPythonTypeConstructor, self).__init__(name, None)
- if (name == "typing.ClassVar" and template_type
- and not template_type.is_pyobject):
- # because classvars end up essentially used as globals they have
- # to be PyObjects. Try to find the nearest suitable type (although
- # practically I doubt this matters).
- py_type_name = template_type.py_type_name()
- if py_type_name:
- from .Builtin import builtin_scope
- template_type = (builtin_scope.lookup_type(py_type_name)
- or py_object_type)
- else:
- template_type = py_object_types
- self.template_type = template_type
+ def __init__(self, name):
+ super(SpecialPythonTypeConstructor, self).__init__(name, base_type=None)
+ self.modifier_name = name
def __repr__(self):
- if self.template_type:
- return "%s[%r]" % (self.name, self.template_type)
- else:
- return self.name
-
- def is_template_type(self):
- return self.template_type is None
+ return self.name
def resolve(self):
- if self.template_type:
- return self.template_type.resolve()
- else:
- return self
+ return self
def specialize_here(self, pos, env, template_values=None):
if len(template_values) != 1:
error(pos, "'%s' takes exactly one template argument." % self.name)
- # return a copy of the template type with python_type_constructor_name as an attribute
- # so it can be identified, and a resolve function that gets back to
- # the original type (since types are usually tested with "is")
- new_type = template_values[0]
- if self.python_type_constructor_name == "typing.ClassVar":
- # classvar must remain a py_object_type
- new_type = py_object_type
- if (self.python_type_constructor_name == "typing.Optional" and
- not new_type.is_pyobject):
- # optional must be a py_object, but can be a specialized py_object
- new_type = py_object_type
- return SpecialPythonTypeConstructor(
- self.python_type_constructor_name,
- template_type = template_values[0])
-
- def __getattr__(self, name):
- if self.template_type:
- return getattr(self.template_type, name)
- return super(SpecialPythonTypeConstructor, self).__getattr__(name)
+ return error_type
+ if template_values[0] is None:
+ # FIXME: allowing unknown types for now since we don't recognise all Python types.
+ return None
+ # Replace this type with the actual 'template' argument.
+ return template_values[0].resolve()
rank_to_type_name = (