Create new ndarray and return PyArray with PyO3

I've been experimenting with using PyO3 to interface Rust and Python. I've run into a road block creating PyArrays from ndarrays, because I can't understand the compiler error.

The code is:

#[pyfunction]
fn test_function(n_elem: usize) -> Py<PyArray<f64, Ix1>>{

    let arr = Array::linspace(0_f64, 2_f64*PI, n_elem);
    let pyarr = Python::with_gil(|py| {
        PyArray::from_owned_array_bound(py, arr).unbind()
    });
    pyarr
}

And the error is:

error[E0308]: mismatched types
    --> src/lib.rs:109:45
     |
109  |         PyArray::from_owned_array_bound(py, arr).unbind()
     |         -------------------------------     ^^^ expected `ArrayBase<OwnedRepr<_>, _>`, found `ArrayBase<OwnedRepr<f64>, Dim<[usize; 1]>>`
     |         |
     |         arguments to this function are incorrect
     |
     = note: `ArrayBase<OwnedRepr<f64>, Dim<[usize; 1]>>` and `ArrayBase<OwnedRepr<_>, _>` have similar names, but are actually distinct types

These look consistent to me, so can anyone tell me what I'm missing?

I cannot reproduce the error. The code compiles fine with pyo3 = 0.22.6 and numpy = 0.22.1 and this header:

use std::f64::consts::PI;
use pyo3::prelude::*;
use numpy::ndarray::prelude::*;
use numpy::PyArray;

Are you using a different ndarray version than numpy?

2 Likes

You can check for different versions of dependencies with cargo tree --duplicates.

2 Likes

That was it, I misunderstood how the import system was working, thanks!

I think this note could be improved. In this case they are the same name (once you fill in _s), not just similar names.

Suggesting to check (or even telling you) whether these are from different versions of the same crate would be helpful.

3 Likes

I think actually it does indicate that later in the stack trace, I just didn't have the experience to recognise the significance of what it was telling me:

     |
109  |         PyArray::from_owned_array_bound(py, arr).unbind()
     |         -------------------------------     ^^^ expected `ArrayBase<OwnedRepr<_>, _>`, found `ArrayBase<OwnedRepr<f64>, Dim<[usize; 1]>>`
     |         |
     |         arguments to this function are incorrect
     |
     = note: `ArrayBase<OwnedRepr<f64>, Dim<[usize; 1]>>` and `ArrayBase<OwnedRepr<_>, _>` have similar names, but are actually distinct types
note: `ArrayBase<OwnedRepr<f64>, Dim<[usize; 1]>>` is defined in crate `ndarray`
    --> /home/[user]/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ndarray-0.16.1/src/lib.rs:1280:1
     |
1280 | pub struct ArrayBase<S, D>
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: `ArrayBase<OwnedRepr<_>, _>` is defined in crate `ndarray`
    --> /home/[user]/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ndarray-0.15.6/src/lib.rs:1268:1
     |
1268 | pub struct ArrayBase<S, D>
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^

     = note: perhaps two different versions of crate `ndarray` are being used?