pub fn broadcast<E>(&self, dim: E) -> Option<ArrayView<'_, A, E::Dim>>
where
E: IntoDimension,
S: Data,
Why does the API tie the lifetime of the view to self? Is the prototype given by elision correct?That is, something like aview1(x).into_shape((4, 5)).unwrap().broadcast((3, 4, 5)).unwrap() isn't allowed by the borrow checker. I want the lifetime in the broadcast to be just constrained by the original x. Does the result require the self bound?
The underlying array data is shared - that is, broadcast() does not copy the underlying data. So the result of a broadcast has to be lifetime-entangled to the original array.
And the code you showed compiles OK for me:
fn main() {
use ndarray::aview1;
let init = [0i32; 20];
let _ = aview1(&init)
.into_shape((4, 5))
.unwrap()
.broadcast((3, 4, 5))
.unwrap();
}
It only compiles because you drop both the temporary created by into_shape and the result of broadcast at the same time.
If you attempt to save the value and use it later, you get a complaint that the temporary created by into_shape does not live long enough (Rust Playground):
use ndarray::aview1;
fn main() {
let x = [0i32; 20];
let n = aview1(&x)
.into_shape((4, 5))
.unwrap()
.broadcast((3, 4, 5))
.unwrap();
dbg!(n);
}
complains:
Compiling playground v0.0.1 (/playground)
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:5:13
|
5 | let n = aview1(&x)
| _____________^
6 | | .into_shape((4, 5))
7 | | .unwrap()
| |_________________^ creates a temporary value which is freed while still in use
8 | .broadcast((3, 4, 5))
9 | .unwrap();
| - temporary value is freed at the end of this statement
10 |
11 | dbg!(n);
| - borrow later used here
|
help: consider using a `let` binding to create a longer lived value
|
5 ~ let binding = aview1(&x)
6 + .into_shape((4, 5))
7 + .unwrap();
8 ~ let n = binding
|
For more information about this error, try `rustc --explain E0716`.
error: could not compile `playground` (bin "playground") due to previous error
I'm sorry my question wasn't clear. There are two lifetimes at play: the lifetime of x and the lifetime of the borrowed ArrayView. I want the lifetime of the broadcast to be tied to x because I don't want to have to name the view.
The lifetime of &x is part of a generic type from the point of view of ArrayBase::broadcast:
let x = [0i32; 20];
// pub fn aview1<A>(xs: &[A]) -> ArrayView1<'_, A>
// alias => ArrayView<'a, A, Ix1>
// alias => ArrayBase<ViewRepr<&'a A>, D>
// That's `ArrayBase<S, D>` with `S = ViewRepr<&'a A>`
let n = aview1(&x)
// pub fn into_shape<E>(self, shape: E) -> Result<ArrayBase<S, E::Dim>, ShapeError>
.into_shape((4, 5))
.unwrap();
// Now you have an `ArrayBase<S, X>` with `S = ViewRepr<&'a A>`
// The `'a` and `A` aren't "visible" to `ArrayBase<S, X>`
let n = n
// pub fn broadcast<E>(&self, dim: E) -> Option<ArrayView<'_, X, E::Dim>>
.broadcast((3, 4, 5))
.unwrap();
So the closest you could get to a signature that works is something like...
But that is only sound if you know a lot about S and know you're basically doing a reborrow of some reference or similar. If S is a 'static type for example, that signature is unsound.
So practically speaking, there's probably no way to get the inner lifetime into the result of broadcast.