diff options
author | da-woods <dw-git@d-woods.co.uk> | 2020-04-18 13:59:06 +0100 |
---|---|---|
committer | da-woods <dw-git@d-woods.co.uk> | 2020-04-18 14:22:29 +0100 |
commit | f22704c1abc718a12e28a7eae49dda82ab945a2d (patch) | |
tree | 2ceeb7e7c8cd089ac32993a8b83a6b87ba973b50 | |
parent | 35ef5e01f9612acde39c2910914f5666d3b2d89e (diff) | |
download | cython-f22704c1abc718a12e28a7eae49dda82ab945a2d.tar.gz |
Added "analyse_as_specialized_type"
-rw-r--r-- | Cython/Compiler/ExprNodes.py | 33 | ||||
-rw-r--r-- | Cython/Compiler/ParseTreeTransforms.py | 5 |
2 files changed, 18 insertions, 20 deletions
diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index ef51b32e3..ad6d6b6c2 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -655,6 +655,19 @@ class ExprNode(Node): # type, return that type, else None. return None + def analyse_as_specialized_type(self, env): + type = self.analyse_as_type(env) + if type.is_fused and env.fused_to_specific: + # while it would be nice to test "if entry.type in env.fused_to_specific" + # rather than try/catch this doesn't work reliably (mainly for nested fused types) + try: + return type.specialize(env.fused_to_specific) + except KeyError: + pass + if type.is_fused: + error(self.pos, "Type is not specific") + return type + def analyse_as_extension_type(self, env): # If this node can be interpreted as a reference to an # extension type or builtin type, return its type, else None. @@ -1961,11 +1974,6 @@ class NameNode(AtomicExprNode): if not entry: entry = env.lookup(self.name) if entry and entry.is_type: - if entry.type.is_fused and env.fused_to_specific: - if entry.type in env.fused_to_specific: - return entry.type.specialize(env.fused_to_specific) - # else lots of valid reasons why we may not be able to get a specific type - # so don't fail return entry.type else: return None @@ -6906,19 +6914,14 @@ class AttributeNode(ExprNode): return None def analyse_as_type(self, env): - tp = None module_scope = self.obj.analyse_as_module(env) if module_scope: - tp = module_scope.lookup_type(self.attribute) - elif not self.obj.is_string_literal: + return module_scope.lookup_type(self.attribute) + if not self.obj.is_string_literal: base_type = self.obj.analyse_as_type(env) if base_type and hasattr(base_type, 'scope') and base_type.scope is not None: - tp = base_type.scope.lookup_type(self.attribute) - if tp and tp.is_fused and env.fused_to_specific: - if tp in env.fused_to_specific: - tp = tp.specialize(env.fused_to_specific) - # else just use unspecialized type - return tp + return base_type.scope.lookup_type(self.attribute) + return None def analyse_as_extension_type(self, env): # Try to interpret this as a reference to an extension type @@ -10836,7 +10839,7 @@ class TypeidNode(ExprNode): self.error("The 'libcpp.typeinfo' module must be cimported to use the typeid() operator") return self self.type = type_info - as_type = self.operand.analyse_as_type(env) + as_type = self.operand.analyse_as_specialized_type(env) if as_type: self.arg_type = as_type self.is_type = True diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index abd24b0d5..e61c3c09c 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -3279,12 +3279,7 @@ class ReplaceFusedTypeChecks(VisitorTransform): def visit_PrimaryCmpNode(self, node): with Errors.local_errors(ignore=True): type1 = node.operand1.analyse_as_type(self.local_scope) - # type2 should not be specialized here as a special case - # we always want to check against the global fused type - fused_to_specific = self.local_scope.fused_to_specific - self.local_scope.fused_to_specific = None type2 = node.operand2.analyse_as_type(self.local_scope) - self.local_scope.fused_to_specific = fused_to_specific if type1 and type2: false_node = ExprNodes.BoolNode(node.pos, value=False) |