Repository: numba/numba

Issue:
np.kron fails to compile under njit with call signature
- [ -] I am using the latest released version of Numba (most recent is visible in
 the change log (https://github.com/numba/numba/blob/master/CHANGE_LOG).
- [- ] I have included below a minimal working reproducer (if you are unsure how
 to write one see http://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports).

The following fails to compile

```
@nb.njit("b1[:, :](b1[:])")
def f(x):
    y = np.atleast_2d(x)
    return np.kron(y, y.T[:])
```

yet it compiles without the call string

```
@nb.njit
def f(x):
    y = np.atleast_2d(x)
    return np.kron(y, y.T[:])
```


Discussion:
Thanks for the report, I can reproduce. The issue here is that when supplying the signature, the type of `x` is seeded by `b1[:]`, which is saying "this is a 1D array of boolean type and unknown layout", i.e.:
```
eval('b1[:]', numba.types.__dict__)
```
gives:
```
array(bool, 1d, A)
```
as a result of this, `np.atleast_2d(x)` leads to `y` being of type `array(bool, 2d, A)` and then the implementation of `np.kron` uses `.reshape()` which is not supported for the `unknown layout`. Admittedly the error message could be easier to understand!

In the case of with no supplied signature, nothing actually get's compiled until a call is made with real inputs, and it's the type of these inputs that seed type inference and compilation will specialise to those. You can create the same error without the signature like this:
```python
import numpy as np
from numba import njit, typeof

@njit
def f(x):
    y = np.atleast_2d(x)
    return np.kron(y, y.T[:])

z = np.empty((10,), np.bool_)[::2]
print(typeof(z)) # prints array(bool, 1d, A)
f(z)
```
and a slightly different error like this, here, the `y.T[:]` is sliced which again produces the "unknown array layout" as input to `np.kron`/`.reshape`:
```python
import numpy as np
from numba import njit, typeof

@njit
def f(x):
    y = np.atleast_2d(x)
    return np.kron(y, y.T[:])

z = np.empty((10,), np.bool_) # now contiguous
print(typeof(z))
f(z)
```
whereas this:
```python
import numpy as np
from numba import njit, typeof

@njit
def f(x):
    y = np.atleast_2d(x)
    return np.kron(y, y.T)

z = np.ones((10,), np.bool_)
print(typeof(z))
print(f(z))
```
does what you probably want.

Hope this helps.
Going to mark this as a bug because I think `np.kron` should be able to raise a `TypingError` to catch the input it can't handle.

Resolving patch:
diff --git a/numba/targets/linalg.py b/numba/targets/linalg.py
--- a/numba/targets/linalg.py
+++ b/numba/targets/linalg.py
@@ -2683,7 +2683,11 @@ def outer_impl(a, b):
 def _kron_normaliser_impl(x):
     # makes x into a 2d array
     if isinstance(x, types.Array):
-        if x.ndim == 2:
+        if x.layout not in ('C', 'F'):
+            raise TypingError("np.linalg.kron only supports 'C' or 'F' layout "
+                              "input arrays. Receieved an input of "
+                              "layout '{}'.".format(x.layout))
+        elif x.ndim == 2:
             @register_jitable
             def nrm_shape(x):
                 xn = x.shape[-1]


Test patch:
diff --git a/numba/tests/test_linalg.py b/numba/tests/test_linalg.py
--- a/numba/tests/test_linalg.py
+++ b/numba/tests/test_linalg.py
@@ -2448,6 +2448,10 @@ def check(a, b, **kwargs):
 
         self._assert_wrong_dim("kron", cfunc)
 
+        args = (np.empty(10)[::2], np.empty(10)[::2])
+        msg = "only supports 'C' or 'F' layout"
+        self.assert_error(cfunc, args, msg, err=errors.TypingError)
+
 
 if __name__ == '__main__':
     unittest.main()