Cannot return value referencing local variable `xxxx`

fn add_value(value: u8, bytes: &[u8]) -> Box<&[u8]> {
    let mut data_vec = bytes.to_vec();
    let add_value = &[value];
    data_vec.splice(0..0, add_value.iter().cloned());
    let bytes = data_vec.as_slice().clone();
        // -------- `data_vec` is borrowed here
        // How to fix it?
    Box::new(bytes)
}

fn encrypt(encrypt_data_bytes: &[u8]) {
    add_value(1, encrypt_data_bytes);
    // I want encrypt_data_bytes values: [1, 2, 3, 4, 5]
}

fn main() {
    let bytes: [u8; 4] = [2, 3, 4, 5];
    encrypt(&bytes);
}

How can I fix it?

Are there any friends who are proficient in Rust, can you tell me how to learn Rust, and recommend more tutorials for novices?

Change the return type to something that has ownership such as Vec<u8>.

1 Like

Can’t I return the type [u8]

You can, but then the type should be Box<[u8]> without the ampersand.

1 Like

No error or error, prompt

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> src/main.rs:8:5
  |
8 |     Box::new(*bytes)
  |     ^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `Sized` is not implemented for `[u8]`
  = note: all function arguments must have a statically known size

The easiest way to create a Box<[u8]> is to first create a Vec<u8>, then call into_boxed_slice.

fn add_value(value: u8, bytes: &[u8]) -> Box<[u8]> {
    let mut data_vec = bytes.to_vec();
    let add_value = &[value];
    data_vec.splice(0..0, add_value.iter().cloned());
    data_vec.into_boxed_slice()
}
2 Likes

Why do you guys know this? Are there any good learning suggestions? I don't want to be bothered by these simple questions anymore.

still have a question:
I want to insert element 1 into the first position of the type [u8]. Apart from the above, is there any other better way?
Such as other programming languages

value_list.splice(0, 0, 1);

Above this is the syntax of JavaScript

There is a Vec::insert method for inserting single elements to the vector. Another way would be to do this:

let mut result = vec![10];
result.extend(&other_vector);

Here I use extend to append the vector to the new one.

Regarding the Box<[u8]> thing, it's pretty uncommon to do this. Mostly people just use a vector.

& is borrowing in Rust. It sort-of means "I temporarily let you see the data in have, but it will go away". In your case the data is in a variable, and variables get destroyed at the end of their scope (nearest }), so you can't let anyone outside of a function have a peek at content of a variable inside the function — the data will be gone before you return the view into it.

You have to use a type that isn't borrowing the variable, like Box<[u8]> or Vec<u8>. In Rust the ownership difference between &[u8] and Box<[u8]> is very important. In GC languages it doesn't matter whether something is in a variable or not. In Rust it is a semantically meaningful difference.

1 Like

It's important to note that a type like Box<&[u8]> behaves pretty much exactly like &[u8]. That the outer smart-pointer is owned doesn't change the fact that you have a borrowed type inside it. You just have ownership of a borrow.

2 Likes