Hello everyone!
I've been playing with rust for a short time, and am currently hitting a brick wall while fighting the borrow checker when using the ndarray crate (version 0.7.2). I compiled a minimal example for you to look at.
First version: The ArrayViewMut1
reference and the returned iterator get the same lifetime b' which outlives the lifetime of the reference to the values of the array 'a and the values themselves T.
extern crate ndarray;
use ndarray::{Array2, ArrayViewMut1, Axis};
fn iter_line_elements<'b, 'a: 'b, A: 'a>(line: &'b mut ArrayViewMut1<'a, A>)
-> Box<Iterator<Item=&'a mut A> + 'b> {
Box::new(line.iter_mut())
}
fn main() {
let mut matrix = Array2::from_elem((4, 4), Some(1u32));
for ref mut col in matrix.axis_iter_mut(Axis(1)) {
let _ = iter_line_elements(col);
//Inlining the function works!
//let _ = Box::new(col.iter_mut());
}
}
rustc's (version 1.14.0) output:
src/main.rs|6 col 19 error 495| cannot infer an appropriate lifetime for autoref due to conflicting requirements
|| |
|| 6 | Box::new(line.iter_mut())
|| | ^^^^^^^^
|| |
|| help: consider using an explicit lifetime parameter as shown: fn iter_line_elements<'a:'b, A: 'a>(line: &'a mut ArrayViewMut1<'a, A>)
|| -> Box<Iterator<Item = &'a mut A>+ 'b>
|| --> src/main.rs:5:1
|| |
|| 5 | fn iter_line_elements<'b, 'a: 'b, A: 'a>(line: &'b mut ArrayViewMut1<'a, A>) -> Box<Iterator<Item=&'a mut A> + 'b> {
|| | ^
Ok, I'm not sure I understand that suggestion, but let's try:
fn iter_line_elements<'b, 'a: 'b, A: 'a>(line: &'a mut ArrayViewMut1<'a, A>)
-> Box<Iterator<Item=&'a mut A> + 'b> {
Box::new(line.iter_mut())
}
I deviated slightly from rustc's suggestion as it fails to declare 'b (why?). Now rustc reports the following error, but does not give any suggestions on how to fix that:
src/main.rs|21 col 5 error| borrowed value does not live long enough
|| |
|| 18 | for ref mut col in matrix.axis_iter_mut(Axis(1)) {
|| | ----------- borrow occurs here
|| ...
|| 21 | }
|| | ^ borrowed value dropped here while still borrowed
|| |
|| = note: values in a scope are dropped in the opposite order they are created
I guess because the lifetimes of the referenced values (within ArrayViewMut
) and the reference to the ArrayViewMut
struct are the same, the borrow checker assumes that col
has to live as long as matrix
. Is that correct?
How would I have to change the signature to allow for a successful compilation? I feel that the first version should compile and do not really understand the reason why compilation fails.
Any help would be appreciated!