Repository: numba/numba

Issue:
Ellipsis incorrectly treated as constant
When all ellipsis is used and all other indices are constant, the ellipsis is incorrectly handled as constant in the lowering.

``` python
@njit
def udt(arr):
    return arr[..., 0]
```

Results in:

```
Internal error:
NotImplementedError: cannot lower constant of type '...'
```



Discussion:

Resolving patch:
diff --git a/numba/lowering.py b/numba/lowering.py
--- a/numba/lowering.py
+++ b/numba/lowering.py
@@ -373,21 +373,10 @@ def lower_assign(self, ty, inst):
         # In nopython mode, closure vars are frozen like globals
         if isinstance(value, (ir.Const, ir.Global, ir.FreeVar)):
             if isinstance(ty, types.ExternalFunctionPointer):
-                res = self.context.get_constant_generic(self.builder, ty,
-                                                        value.value)
                 self.has_dynamic_globals = True
 
-            elif isinstance(ty, types.Dummy):
-                res = self.context.get_dummy_value()
-
-            elif isinstance(ty, types.Array):
-                res = self.context.make_constant_array(self.builder, ty,
-                                                       value.value)
-
-            else:
-                res = self.context.get_constant_generic(self.builder, ty,
-                                                        value.value)
-
+            res = self.context.get_constant_generic(self.builder, ty,
+                                                    value.value)
             self.incref(ty, res)
             return res
 
diff --git a/numba/targets/base.py b/numba/targets/base.py
--- a/numba/targets/base.py
+++ b/numba/targets/base.py
@@ -334,7 +334,19 @@ def get_constant_generic(self, builder, ty, val):
         """
         Return a LLVM constant representing value *val* of Numba type *ty*.
         """
-        if self.is_struct_type(ty):
+        if isinstance(ty, types.ExternalFunctionPointer):
+            ptrty = self.get_function_pointer_type(ty)
+            ptrval = ty.get_pointer(val)
+            return builder.inttoptr(self.get_constant(types.intp, ptrval),
+                                    ptrty)
+
+        elif isinstance(ty, types.Array):
+            return self.make_constant_array(builder, ty, val)
+
+        elif isinstance(ty, types.Dummy):
+            return self.get_dummy_value()
+
+        elif self.is_struct_type(ty):
             struct = self.get_constant_struct(builder, ty, val)
             if isinstance(ty, types.Record):
                 ptrty = self.data_model_manager[ty].get_data_type()
@@ -343,12 +355,6 @@ def get_constant_generic(self, builder, ty, val):
                 return ptr
             return struct
 
-        elif isinstance(ty, types.ExternalFunctionPointer):
-            ptrty = self.get_function_pointer_type(ty)
-            ptrval = ty.get_pointer(val)
-            return builder.inttoptr(self.get_constant(types.intp, ptrval),
-                                    ptrty)
-
         else:
             return self.get_constant(ty, val)
 


Test patch:
diff --git a/numba/tests/test_indexing.py b/numba/tests/test_indexing.py
--- a/numba/tests/test_indexing.py
+++ b/numba/tests/test_indexing.py
@@ -651,6 +651,18 @@ def udt(arr):
         expected = py_func(arr)
         np.testing.assert_equal(got, expected)
 
+    def test_ellipsis_issue1499(self):
+        # This tests an issue when ndarray.__getitem__ recv a tuple of
+        # constants. The lowering is mishandling the constant value creation.
+        @njit
+        def udt(arr):
+            return arr[..., 0]
+
+        arr = np.arange(3)
+        got = udt(arr)
+        expected = udt.py_func(arr)
+        np.testing.assert_equal(got, expected)
+
     def test_none_index(self, flags=enable_pyobj_flags):
         pyfunc = none_index_usecase
         arraytype = types.Array(types.int32, 2, 'C')