"borrowed value is not long enough" when using a slice structure

I have the following code snippet:

extern crate debug; use std::mem::size_of_val; struct A<'a> { a: &'a [i64], } fn main() { // code } 

When I define a slice with & (ie &[1, 2, 3] ), as in the following println!

 println!("{} - {:?}", size_of_val(&A { a: &[1, 2, 3] }), A { a: &[1, 2, 3] }); 

conclusion

 16 - A<'static>{a: &[1i64, 2i64, 3i64]} 

Determination of cut-off without &

 println!("{} - {:?}", size_of_val(&A { a: [1, 2, 3] }), A { a: [1, 2, 3] }); 

gives the same result

 16 - A<'static>{a: &[1i64, 2i64, 3i64]} 

If I first try to bind an instance of struct A whose field A initialized with a slice reference (i.e. using & ) to the variable x

 let x = A { a: &[1, 2, 3] }; // &[1, 2, 3] is a reference to a slice 

and I'm trying to do a similar println! like previous

 println!("{} - {:?}", size_of_val(&x), x); 

I get

 16 - A<'static>{a: &[1i64, 2i64, 3i64]} 

However, if I bind an instance of A whose field A initialized with a slice (not a reference to the slice using & ), the variable x

 let x = A { a: [1, 2, 3] }; 

and I'm trying to do a similar println! like previous

 println!("{} - {:?}", size_of_val(&x), x); 

I get the following build error:

 /prpath/main.rs:12:20: 12:29 error: borrowed value does not live long enough /prpath/main.rs:12 let x = A { a: [1 ,2, 3] }; ^~~~~~~~~ /prpath/main.rs:11:11: 15:2 note: reference must be valid for the block at 11:10... /prpath/main.rs:11 fn main() { /prpath/main.rs:12 let x = A { a: [1 ,2, 3] }; /prpath/main.rs:13 /prpath/main.rs:14 println!("{} - `{:?}`", size_of_val(&x), x); /prpath/main.rs:15 } /prpath/main.rs:12:5: 12:31 note: ...but borrowed value is only valid for the statement at 12:4; consider using a `let` binding to increase its lifetime /prpath/main.rs:12 let x = A { a: [1 ,2, 3] }; ^~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error 

I expected that only the definition of A { a: &[1, 2, 3] } was allowed, because Aa should be of type &[i64] , but Rust seems to let us not include the & character.

What is the difference between A { a: &[1, 2, 3] } and A { a: [1, 2, 3] } ? Why are we allowed to use A { a: [1, 2, 3] } (in the second example above)?

+5
source share
1 answer

First, you can use [T,..n] , where &[T] is expected, conversion to slice is implicit. Thus, the following code is absolutely correct:

 let a = [1u, 2, 3]; let b: &[uint] = a; 

Your situation is a purely lifelong problem. Your structure

 struct A<'a> { a: &'a [i64], } 

It contains a slice . A slice is nothing more than a reference to the first element and a count of the number of elements. Therefore, size_of_val() , called in A , will always return 16: the slice size, one u64 for the pointer and one u64 for the number of elements (as you seem on a 64-bit computer).

So, in your code, the structure does not own the array . The difference in behavior that you observe is related to the difference in when the array goes out of scope.

The first case:

 let x = A { a: [1, 2, 3] }; 

Here you define an array and save a fragment of this array in your structure. Then when you reach ; , your array goes out of scope and is destroyed, and therefore the reference in x no longer valid: this is forbidden by the compiler.

Second case:

 let x = A { a: &[1, 2, 3] }; 

This is weirder. Your array is stored in an anonymous variable. In fact, I write

 let foo = &42u; 

equivalent to writing

 let _anonymousvariable = 42u; let foo = &_anonymousvariable; 

Except that you cannot reach _anonymousvariable directly.

This is exactly the same for you, your code is equivalent

 let _anonymous_array = [1, 2, 3] let x = A { a: &_anonymous_array }; 

and thus quite rightly.

Last case:

When you write everything directly in println!() . Thanks to the previous case, we now see why this works:

 println!("{} - {:?}", size_of_val(&A { a: &[1, 2, 3] }), A { a: &[1, 2, 3] }); 

but in this case there is no problem:

 println!("{} - {:?}", size_of_val(&A { a: [1, 2, 3] }), A { a: [1, 2, 3] }); 

because your arrays go beyond the scope when reaching ; , and no link to them exists at this point, so they can be safely deleted and the compiler will be happy.

+5
source

Source: https://habr.com/ru/post/1204932/


All Articles