disable type inference for closures and work around prematurely created closure field...
authorStefan Behnel <scoder@users.berlios.de>
Sat, 20 Mar 2010 12:27:50 +0000 (13:27 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Sat, 20 Mar 2010 12:27:50 +0000 (13:27 +0100)
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/TypeInference.py

index 36cd2ee8a7679a3438bf3439845be361efc1f90e..ac399041fdf382674753fc72387c2740ceceb763 100644 (file)
@@ -1207,6 +1207,10 @@ class CreateClosureClasses(CythonTransform):
         for entry in func_scope.entries.values():
             # This is wasteful--we should do this later when we know
             # which vars are actually being used inside...
+            #
+            # Also, this happens before type inference and type
+            # analysis, so the entries created here may end up having
+            # incorrect or at least unspecified types.
             cname = entry.cname
             class_scope.declare_var(pos=entry.pos,
                                     name=entry.name,
index 5c792db86f8be131f7816b8f1cd42cc765ba4f0b..4b09cfef93f18a38b5afd0573ffee21421ee9598 100644 (file)
@@ -188,7 +188,7 @@ class SimpleAssignmentTypeInferer:
     # TODO: Implement a real type inference algorithm.
     # (Something more powerful than just extending this one...)
     def infer_types(self, scope):
-        enabled = scope.directives['infer_types']
+        enabled = not scope.is_closure_scope and scope.directives['infer_types']
         verbose = scope.directives['infer_types.verbose']
         if enabled == True:
             spanning_type = aggressive_spanning_type
@@ -198,6 +198,8 @@ class SimpleAssignmentTypeInferer:
             for entry in scope.entries.values():
                 if entry.type is unspecified_type:
                     entry.type = py_object_type
+            if scope.is_closure_scope:
+                fix_closure_entries(scope)
             return
 
         dependancies_by_entry = {} # entry -> dependancies
@@ -259,6 +261,19 @@ class SimpleAssignmentTypeInferer:
             entry.type = py_object_type
             if verbose:
                 message(entry.pos, "inferred '%s' to be of type '%s' (default)" % (entry.name, entry.type))
+        #if scope.is_closure_scope:
+        #    fix_closure_entries(scope)
+
+def fix_closure_entries(scope):
+    """Temporary work-around to fix field types in the closure class
+    that were unknown at the time of creation and only determined
+    during type inference.
+    """
+    closure_entries = scope.scope_class.type.scope.entries
+    for name, entry in scope.entries.iteritems():
+        if name in closure_entries:
+            closure_entry = closure_entries[name]
+            closure_entry.type = entry.type
 
 def find_spanning_type(type1, type2):
     if type1 is type2: