Coming from this code template which works:
{
fn f3( _s : &String) {}
fn f( s : &String) -> impl FnMut() {
let s2 = s.clone();
move || f3( &s2)
}
let mut f2 = f( &"123".to_string());
f2();
}
If I modify the code this way:
{
fn f3( _s : &[u8]) {}
fn f( s : &[u8]) -> impl FnMut() {
// let s2 = s.clone(); // don't work
let s2 = Vec::from(s);
move || f3( &s2[..])
}
let mut f2 = f( &vec![1u8][..]);
f2();
}
I cannot use 'let s2 = s.clone();'. This brings the error message:
1169 | fn f( s : &[u8]) -> impl FnMut() {
| ------------ this return type evaluates to the `'static` lifetime...
1170 | let s2 = s.clone();
| ^^^^^ ...but this borrow...
|
note: ...can't outlive the anonymous lifetime #1 defined on the function body at 1169:3
How can clone initiate a borrow?
In your first example, s
is a &String
, and String
implements Clone
, so the clone(&self)
method is used.
In your second example, s
is a &[u8]
, and [u8]
does not implement Clone
. So instead you are using the blanket implementation for &T
where T
is any type; that is, you are cloning the reference, not the thing being referenced. The result is another reference to the same thing, hence it is still a borrow.
The solution in this case is to use a different method than .clone()
to create an owned copy of the slice. As you've noticed, Vec::from
works, and gives you a Vec<u8>
; you can also use Box::from
to get a Box<[u8]>
. You can't (currently) get a raw [u8]
as a local variable, since that is an unsized type, so the use of ::from
here is because you need to choose what other type your owned copy will be.