summaryrefslogtreecommitdiff
path: root/Cython
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2017-07-25 14:49:49 +0200
committerStefan Behnel <stefan_ml@behnel.de>2017-07-25 14:49:49 +0200
commitfb5e92001fe31a49227378e90a77bc5f4e2a83ff (patch)
treefcd4b4fc7ea273b6c071c761598e77a2dff20982 /Cython
parent66dc4405ddbc43730417c22e44626869aadce193 (diff)
downloadcython-fb5e92001fe31a49227378e90a77bc5f4e2a83ff.tar.gz
Suppress special casing of attribute names in closure classes since they are not user defined and any local variable name is allowed without being special.
Closes #1797.
Diffstat (limited to 'Cython')
-rw-r--r--Cython/Compiler/ModuleNode.py8
-rw-r--r--Cython/Compiler/ParseTreeTransforms.py1
-rw-r--r--Cython/Compiler/Symtab.py11
-rw-r--r--Cython/Compiler/TypeSlots.py2
4 files changed, 12 insertions, 10 deletions
diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py
index 2949ceeb6..311afcfb9 100644
--- a/Cython/Compiler/ModuleNode.py
+++ b/Cython/Compiler/ModuleNode.py
@@ -1334,11 +1334,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
is_final_type = scope.parent_type.is_final_type
needs_gc = scope.needs_gc()
- weakref_slot = scope.lookup_here("__weakref__")
+ weakref_slot = scope.lookup_here("__weakref__") if not scope.is_closure_class_scope else None
if weakref_slot not in scope.var_entries:
weakref_slot = None
- dict_slot = scope.lookup_here("__dict__")
+ dict_slot = scope.lookup_here("__dict__") if not scope.is_closure_class_scope else None
if dict_slot not in scope.var_entries:
dict_slot = None
@@ -2800,7 +2800,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
scope.class_name,
typeobj_cname,
code.error_goto(entry.pos)))
- weakref_entry = scope.lookup_here("__weakref__")
+ weakref_entry = scope.lookup_here("__weakref__") if not scope.is_closure_class_scope else None
if weakref_entry:
if weakref_entry.type is py_object_type:
tp_weaklistoffset = "%s.tp_weaklistoffset" % typeobj_cname
@@ -2815,7 +2815,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
weakref_entry.cname))
else:
error(weakref_entry.pos, "__weakref__ slot must be of type 'object'")
- if scope.lookup_here("__reduce_cython__"):
+ if scope.lookup_here("__reduce_cython__") if not scope.is_closure_class_scope else None:
# Unfortunately, we cannot reliably detect whether a
# superclass defined __reduce__ at compile time, so we must
# do so at runtime.
diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py
index 49b280389..e7ba2c55b 100644
--- a/Cython/Compiler/ParseTreeTransforms.py
+++ b/Cython/Compiler/ParseTreeTransforms.py
@@ -2632,6 +2632,7 @@ class CreateClosureClasses(CythonTransform):
func_scope.scope_class = entry
class_scope = entry.type.scope
class_scope.is_internal = True
+ class_scope.is_closure_class_scope = True
if Options.closure_freelist_size:
class_scope.directives['freelist'] = Options.closure_freelist_size
diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py
index 248e6c4bb..3ed21a47e 100644
--- a/Cython/Compiler/Symtab.py
+++ b/Cython/Compiler/Symtab.py
@@ -1917,6 +1917,7 @@ class CClassScope(ClassScope):
# inherited_var_entries [Entry] Adapted var entries from base class
is_c_class_scope = 1
+ is_closure_class_scope = False
has_pyobject_attrs = False
has_memoryview_attrs = False
@@ -1960,7 +1961,7 @@ class CClassScope(ClassScope):
for entry in self.var_entries:
if entry.type.is_pyobject:
- if include_weakref or entry.name != "__weakref__":
+ if include_weakref or (self.is_closure_class_scope or entry.name != "__weakref__"):
if include_gc_simple or not entry.type.is_gc_simple:
py_attrs.append(entry)
elif entry.type == PyrexTypes.c_py_buffer_type:
@@ -1980,7 +1981,7 @@ class CClassScope(ClassScope):
error(pos,
"C attributes cannot be added in implementation part of"
" extension type defined in a pxd")
- if get_special_method_signature(name):
+ if not self.is_closure_class_scope and get_special_method_signature(name):
error(pos,
"The name '%s' is reserved for a special method."
% name)
@@ -1998,7 +1999,7 @@ class CClassScope(ClassScope):
self.has_memoryview_attrs = True
elif type.is_cpp_class:
self.has_cpp_class_attrs = True
- elif type.is_pyobject and name != '__weakref__':
+ elif type.is_pyobject and (self.is_closure_class_scope or name != '__weakref__'):
self.has_pyobject_attrs = True
if (not type.is_builtin_type
or not type.scope or type.scope.needs_gc()):
@@ -2011,7 +2012,7 @@ class CClassScope(ClassScope):
# so do conversion ourself rather than rely on the CPython mechanism (through
# a property; made in AnalyseDeclarationsTransform).
entry.needs_property = True
- if name == "__weakref__":
+ if not self.is_closure_class_scope and name == "__weakref__":
error(pos, "Special attribute __weakref__ cannot be exposed to Python")
if not (type.is_pyobject or type.can_coerce_to_pyobject(self)):
# we're not testing for coercion *from* Python here - that would fail later
@@ -2056,7 +2057,7 @@ class CClassScope(ClassScope):
return entry
def lookup_here(self, name):
- if name == "__new__":
+ if not self.is_closure_class_scope and name == "__new__":
name = EncodedString("__cinit__")
entry = ClassScope.lookup_here(self, name)
if entry and entry.is_builtin_cmethod:
diff --git a/Cython/Compiler/TypeSlots.py b/Cython/Compiler/TypeSlots.py
index b25b4adb8..c764f7261 100644
--- a/Cython/Compiler/TypeSlots.py
+++ b/Cython/Compiler/TypeSlots.py
@@ -519,7 +519,7 @@ class DictOffsetSlot(SlotDescriptor):
# Slot descriptor for a class' dict offset, for dynamic attributes.
def slot_code(self, scope):
- dict_entry = scope.lookup_here("__dict__")
+ dict_entry = scope.lookup_here("__dict__") if not scope.is_closure_class_scope else None
if dict_entry and dict_entry.is_variable:
if getattr(dict_entry.type, 'cname', None) != 'PyDict_Type':
error(dict_entry.pos, "__dict__ slot must be of type 'dict'")