Repository: numba/numba

Issue:
Lowering error when removing element from the middle of linked list
Hi

I am having a hard time trying to figure out an error when I reassign "element_0.next = element_1.next" of a linked list. I posted my error at stackoverflow: https://stackoverflow.com/questions/47232035/numba-lowering-error-when-reassigning-next-link-of-a-linked-list-element

I am creating this issue to make it closer to you.

I have visited most of your examples and documentation pages, no ideas whatsoever.

What am I missing?

I am using numba **0.35.0** (from Anaconda, python 3.6.2).

Thanks


Discussion:
I can confirm that this is an internal error in the compiler.

Resolving patch:
diff --git a/numba/targets/optional.py b/numba/targets/optional.py
--- a/numba/targets/optional.py
+++ b/numba/targets/optional.py
@@ -1,9 +1,9 @@
 from __future__ import print_function, absolute_import, division
 
-from numba import types, cgutils
+from numba import types, cgutils, typing
 
 from .imputils import (lower_cast, lower_builtin, lower_getattr_generic,
-                       impl_ret_untracked)
+                       impl_ret_untracked, lower_setattr_generic)
 
 
 def always_return_true_impl(context, builder, sig, args):
@@ -53,6 +53,21 @@ def optional_getattr(context, builder, typ, value, attr):
     return imp(context, builder, inner_type, val, attr)
 
 
+@lower_setattr_generic(types.Optional)
+def optional_setattr(context, builder, sig, args, attr):
+    """
+    Optional.__setattr__ => redirect to the wrapped type.
+    """
+    basety, valty = sig.args
+    target, val = args
+    target_type = basety.type
+    target = context.cast(builder, target, basety, target_type)
+
+    newsig = typing.signature(sig.return_type, target_type, valty)
+    imp = context.get_setattr(attr, newsig)
+    return imp(builder, (target, val))
+
+
 @lower_cast(types.Optional, types.Optional)
 def optional_to_optional(context, builder, fromty, toty, val):
     """


Test patch:
diff --git a/numba/tests/test_jitclasses.py b/numba/tests/test_jitclasses.py
--- a/numba/tests/test_jitclasses.py
+++ b/numba/tests/test_jitclasses.py
@@ -220,6 +220,13 @@ def get_next_data(self):
                 # use deferred type as argument
                 return get_data(self.next)
 
+            def append_to_tail(self, other):
+                cur = self
+                while cur.next is not None:
+                    cur = cur.next
+                cur.next = other
+
+
         node_type.define(LinkedNode.class_type.instance_type)
 
         first = LinkedNode(123, None)
@@ -239,6 +246,16 @@ def get_next_data(self):
         first_val = second.get_next_data()
         self.assertEqual(first_val, first.data)
 
+        # Check setattr (issue #2606)
+        self.assertIsNone(first.next)
+        second.append_to_tail(LinkedNode(567, None))
+        self.assertIsNotNone(first.next)
+        self.assertEqual(first.next.data, 567)
+        self.assertIsNone(first.next.next)
+        second.append_to_tail(LinkedNode(678, None))
+        self.assertIsNotNone(first.next.next)
+        self.assertEqual(first.next.next.data, 678)
+
         # Check ownership
         self.assertEqual(first_meminfo.refcount, 3)
         del second, second_meminfo