borrowed value does not live long enough in this case ( Vec<&Fn(i32) -> i32> ) - rust

I am having this error, other times I had something similar and I have been able to solve, in different ways but now is not how to solve in this case:
borrowed value does not live long enough in
I moved the code that fails one more simple, but I can not find the error:
fn main(){
let mut v: Vec<&Fn(i32) -> i32> = Vec::new();
v.push(&ops_code1);
//v.push(&ops_code2);
//v.push(&ops_code3);
}
fn ops_code1(value: i32) -> i32 {
..//
error: borrowed value does not live long enough
v.push(&ops_code1);
play.rust

What you are doing here is creating a Vec of closures. In Rust static functions are treated slightly differently from closures, so when we create the reference a closure is actually created. If we do that after creating the Vec the resulting closure gets a shorter lifetime than the Vec, which is an error. We can instead use a let to create the closure before the Vec, giving a long enough lifetime, outliving the Vec:
fn main() {
let extended = &ops_code1;
let mut v: Vec<&Fn(i32) -> i32> = Vec::new();
// Note that placing it here does not work:
// let extended = &ops_code1;
v.push(extended);
//v.push(&ops_code2);
//v.push(&ops_code3);
}
fn ops_code1(value: i32) -> i32 {
println!("ops_code1 {}", value);
value
}
Rust Playground
However, if you only use static functions - and not closures - the following also works fine, and lets you avoid the extra let:
fn main() {
let mut v: Vec<fn(i32) -> i32> = Vec::new();
v.push(ops_code1);
v.push(ops_code2);
}
fn ops_code1(value: i32) -> i32 {
println!("ops_code1 {}", value);
value
}
fn ops_code2(value: i32) -> i32 {
println!("ops_code2 {}", value);
value
}
Rust Playground
A third option is to use boxed closures, which let's you use both closures and static functions without the extra lets, but with its own trade-offs:
fn main() {
let mut v: Vec<Box<Fn(i32) -> i32>> = Vec::new();
v.push(Box::new(ops_code1));
v.push(Box::new(ops_code2));
for f in v {
f(1);
}
}
fn ops_code1(value: i32) -> i32 {
println!("ops_code1 {}", value);
value
}
fn ops_code2(value: i32) -> i32 {
println!("ops_code2 {}", value);
value
}
Rust Playground

Related

mutation reference for Box closure, but not live long enough

I'm rather new to rust, I have some problems,I don't know how to describe my problem. I think talk is cheap and I want to show my code, but I must add more detail for post.
// programA
struct ClosureTest {
x: u8,
}
type Executor = Box<dyn FnMut() -> ()>;
impl ClosureTest {
fn new(x: u8) -> Self {
ClosureTest { x }
}
}
struct Ftest {}
impl Ftest {
fn exec(&self, mut executor: Executor) {
executor();
}
}
fn receive_test(arg: &mut ClosureTest) {
arg.x = 6;
println!("{}", arg.x);
}
fn main() {
let mut closure_test = ClosureTest::new(5);
let f_test = Ftest {};
let executor = Box::new(|| {
receive_test(&mut closure_test);
});
f_test.exec(executor);
}
I got these errors:
error[E0597]: `closure_test` does not live long enough
--> src/main.rs:30:23
|
29 | let executor = Box::new(|| {
| -- value captured here
30 | receive_test(&mut closure_test);
| ^^^^^^^^^^^^ borrowed value does not live long enough
...
33 | f_test.exec(executor);
| -------- cast requires that `closure_test` is borrowed for `'static`
34 | }
| - `closure_test` dropped here while still borrowed
But if I use mut reference like follows, it works fine.
// programB
struct ClosureTest {
x: u8,
}
type Executor<'a> = &'a mut dyn FnMut() -> ();
impl ClosureTest {
fn new(x: u8) -> Self {
ClosureTest { x }
}
}
struct Ftest {}
impl Ftest {
fn exec(&self, executor: Executor) {
executor();
}
}
fn receive_test(arg: &mut ClosureTest) {
arg.x = 6;
println!("{}", arg.x);
}
fn main() {
let mut closure_test = ClosureTest::new(5);
let f_test = Ftest {};
let mut executor = || {
receive_test(&mut closure_test);
};
f_test.exec(&mut executor);
}
So
What's the reason cause this difference.
Why in sync program "programA" will cause lifetime error?
closure_test is drop before f_test.exec(executor)? or after?
To understand what is happening here you'll need to make a little dive into the Rust Book and learn about lifetimes.
I'll simplify for sake of explanation and comment this:
//type Executor = Box< dyn FnMut() -> ()>;
And change the signature of exec function to this:
fn exec(&self, mut executor: Box<dyn FnMut() -> () >) {
executor();
}
First of all let's notice that if we will comment very last line:
//f_test.exec(executor);
the error is gone. The reason for this is that reference to the closure you created - &Box<dyn FnMut() -> ()> has shorter lifetime than other part of main (it's scoped). It means that when you are creating this closure it exists, but just after the reference to this is dropped. That's why it doesn't complain if you not use it, because it's all okay.
Lifetimes are not variables, they are claims, kinda of similar to generics.
If you would change right now the signature of function exec function to this:
impl Ftest {
fn exec<'a>(&self, mut executor: Box<dyn FnMut() -> () + 'a>) {
executor();
}
}
I would say this:
let's say that lifetime of my function is a,
it would takes some parameters and return Box of function which lifetime would be also a, so it would live as long as I.
By doing it we hinted compiler that the lifetime of closure you'll create should live "in same lifetime" as exec() is executed. That's why even if we bring back the last line of main it would work :D.
There is also an option of adding move keyword:
fn main() {
let mut closure_test = ClosureTest::new(5);
let f_test = Ftest {};
let executor = Box::new(move || {
receive_test(&mut closure_test);
});
//println!("{}", closure_test.x);
f_test.exec(executor);
}
This will work, because by adding move keyword we actually tell that we would rather move closure_test object to our scope, not just a reference, therefore it's not dropped. However you wouldn't be able to use it later as shown if you'll uncomment the line with println!().
I'll be happy if anybody would provide some corrections and more details. This concept in Rust is unique and takes time to fully understand so it would be helpful.

Why Rust can't coerce mutable reference to immutable reference in a type constructor?

It is possible to coerce &mut T into &T but it doesn't work if the type mismatch happens within a type constructor.
playground
use ndarray::*; // 0.13.0
fn print(a: &ArrayView1<i32>) {
println!("{:?}", a);
}
pub fn test() {
let mut x = array![1i32, 2, 3];
print(&x.view_mut());
}
For the above code I get following error:
|
9 | print(&x.view_mut());
| ^^^^^^^^^^^^^ types differ in mutability
|
= note: expected reference `&ndarray::ArrayBase<ndarray::ViewRepr<&i32>, ndarray::dimension::dim::Dim<[usize; 1]>>`
found reference `&ndarray::ArrayBase<ndarray::ViewRepr<&mut i32>, ndarray::dimension::dim::Dim<[usize; 1]>>`
It is safe to coerce &mut i32 to &i32 so why it is not applied in this situation? Could you provide some examples on how could it possibly backfire?
In general, it's not safe to coerce Type<&mut T> into Type<&T>.
For example, consider this wrapper type, which is implemented without any unsafe code and is therefore sound:
#[derive(Copy, Clone)]
struct Wrapper<T>(T);
impl<T: Deref> Deref for Wrapper<T> {
type Target = T::Target;
fn deref(&self) -> &T::Target { &self.0 }
}
impl<T: DerefMut> DerefMut for Wrapper<T> {
fn deref_mut(&mut self) -> &mut T::Target { &mut self.0 }
}
This type has the property that &Wrapper<&T> automatically dereferences to &T, and &mut Wrapper<&mut T> automatically dereferences to &mut T. In addition, Wrapper<T> is copyable if T is.
Assume that there exists a function that can take a &Wrapper<&mut T> and coerce it into a &Wrapper<&T>:
fn downgrade_wrapper_ref<'a, 'b, T: ?Sized>(w: &'a Wrapper<&'b mut T>) -> &'a Wrapper<&'b T> {
unsafe {
// the internals of this function is not important
}
}
By using this function, it is possible to get a mutable and immutable reference to the same value at the same time:
fn main() {
let mut value: i32 = 0;
let mut x: Wrapper<&mut i32> = Wrapper(&mut value);
let x_ref: &Wrapper<&mut i32> = &x;
let y_ref: &Wrapper<&i32> = downgrade_wrapper_ref(x_ref);
let y: Wrapper<&i32> = *y_ref;
let a: &mut i32 = &mut *x;
let b: &i32 = &*y;
// these two lines will print the same addresses
// meaning the references point to the same value!
println!("a = {:p}", a as &mut i32); // "a = 0x7ffe56ca6ba4"
println!("b = {:p}", b as &i32); // "b = 0x7ffe56ca6ba4"
}
Full playground example
This is not allowed in Rust, leads to undefined behavior and means that the function downgrade_wrapper_ref is unsound in this case. There may be other specific cases where you, as the programmer, can guarantee that this won't happen, but it still requires you to implement it specifically for those case, using unsafe code, to ensure that you take the responsibility of making those guarantees.
Consider this check for an empty string that relies on content staying unchanged for the runtime of the is_empty function (for illustration purposes only, don't use this in production code):
struct Container<T> {
content: T
}
impl<T> Container<T> {
fn new(content: T) -> Self
{
Self { content }
}
}
impl<'a> Container<&'a String> {
fn is_empty(&self, s: &str) -> bool
{
let str = format!("{}{}", self.content, s);
&str == s
}
}
fn main() {
let mut foo : String = "foo".to_owned();
let container : Container<&mut String> = Container::new(&mut foo);
std::thread::spawn(|| {
container.content.replace_range(1..2, "");
});
println!("an empty str is actually empty: {}", container.is_empty(""))
}
(Playground)
This code does not compile since &mut String does not coerce into &String. If it did, however, it would be possible that the newly created thread changed the content after the format! call but before the equal comparison in the is_empty function, thereby invalidating the assumption that the container's content was immutable, which is required for the empty check.
It seems type coercions don't apply to array elements when array is the function parameter type.
playground

Is it possible to create a wrapper around an &mut that acts like an &mut

The following code fails to compile because MutRef is not Copy. It can not be made copy because &'a mut i32 is not Copy. Is there any way give MutRef similar semantics to &'a mut i32?
The motivation for this is being able to package up a large set of function parameters into a struct so that they can be passed as a group instead of needing to be passed individually.
struct MutRef<'a> {
v: &'a mut i32
}
fn wrapper_use(s: MutRef) {
}
fn raw_use(s: &mut i32) {
}
fn raw_ref() {
let mut s: i32 = 9;
let q = &mut s;
raw_use(q);
raw_use(q);
}
fn wrapper() {
let mut s: i32 = 9;
let q = MutRef{ v: &mut s };
wrapper_use(q);
wrapper_use(q);
}
No.
The name for this feature is "implicit reborrowing" and it happens when you pass a &mut reference where the compiler expects a &mut reference of a possibly different lifetime. The compiler only implicitly reborrows when the actual type and the expected type are both &mut references. It does not work with generic arguments or structs that contain &mut references. There is no way in current Rust to make a custom type that can be implicitly reborrowed. There is an open issue about this limitation dating from 2015, but so far nobody has proposed any way to lift it.
You can always implement your own method to explicitly reborrow:
impl<'a> MutRef<'a> {
// equivalent to fn reborrow(&mut self) -> MutRef<'_>
fn reborrow<'b>(&'b mut self) -> MutRef<'b> {
MutRef {v: self.v}
}
}
fn wrapper() {
let mut s: i32 = 9;
let mut q = MutRef{ v: &mut s };
wrapper_use(q.reborrow()); // does not move q
wrapper_use(q); // moves q
}
See also
Why is the mutable reference not moved here?
Type inference and borrowing vs ownership transfer

Lifetimes issues when placing a match with mutable references into a function

Let's say I have this code (it's contrived, since it's heavily simplified):
enum Foo<'a, T> where T: 'a {
Bar(&'a mut Vec<T>),
}
fn main() {
let mut v = vec![1, 2];
let foo: Foo<isize> = Foo::Bar(&mut v);
let a = match foo {
Foo::Bar(ref mut v) => &mut v[..],
};
a[1] = 10;
println!("a = {:?}", a);
}
This works and everyone is happy. However, if I try to clean it up a bit by placing the match statement inside a function, I can't even get the function to compile, let alone put it to work for me. One of my many attempts looks like this:
fn unpack<'a, T>(foo: Foo<'a, T>) -> &'a mut [T] {
match foo {
Foo::Bar(ref mut v) => &mut v[..],
}
}
I just get the error:
error: `foo.0` does not live long enough
I have been trying to change to multiple lifetimes and adding a where clause (just like I had to do to get the Enum to work), but I can't seem to get it to work. My question is simply if it works (and how) or if the only option here is to use a macro.
Foo::Bar(ref mut v) borrows &mut Vec<T> from foo so it can't outlive foo (which only lives until the end of the function). What you actually want to do is take it (by value) so you should match on Foo::Bar(v):
fn unpack<'a, T>(foo: Foo<'a, T>) -> &'a mut [T] {
match foo {
Foo::Bar(v) => &mut v[..],
}
}
Note: Rust will deref v as needed so the following will also work:
fn unpack<'a, T>(foo: Foo<'a, T>) -> &'a mut [T] {
match foo {
Foo::Bar(v) => v,
}
}

How can I iterate over a vector of functions and call each of them?

I'm trying to use a for loop to iterate over a vector of functions and execute each function at each step.
fn f1(i: i32) -> i32 {
i * 2
}
fn f2(i: i32) -> i32 {
i * 4
}
fn main() {
let mut arr: Vec<|i32| -> i32> = Vec::new();
arr.push(f1);
arr.push(f2);
for f in arr.iter() {
println!("{}", f(1));
}
}
But the attempted execution of f(1) gives this error:
error: expected function, found '&|i32| -> i32'
I guess in putting the functions in the vector their type is mutated and no longer works like a normal function. Is there a way to transform it back, or am I missing something?
As of Rust 1.x, unboxed closures are the only kind of closures in the language, and they don't need a feature flag. Moreover, static functions can easily be converted to unboxed closures. Therefore, the correct way to call functions from a vector of functions is:
fn f1(i: i32) -> i32 { i * 2 }
fn f2(i: i32) -> i32 { i * 4 }
fn main() {
let arr: Vec<&dyn Fn(i32) -> i32> = vec![&f1, &f2];
for f in &arr {
println!("{}", (f)(1));
}
}
I've used Fn() closures which can access their environment through a shared reference, so it is sufficient to iterate the vector by reference. If I had used a FnMut() closure, I would have had to use iteration by mutable reference:
fn f1(i: i32) -> i32 { i * 2 }
fn f2(i: i32) -> i32 { i * 4 }
fn main() {
let p1 = &mut f1;
let p2 = &mut f2;
let mut arr: Vec<&mut dyn FnMut(i32) -> i32> = vec![p1, p2];
for f in &mut arr {
println!("{}", (f)(1));
}
}
A similar idea holds for FnOnce() and iteration by value, although here we need to use Box to own the closure:
fn f1(i: i32) -> i32 { i * 2 }
fn f2(i: i32) -> i32 { i * 4 }
fn main() {
let arr: Vec<Box<dyn FnOnce(i32) -> i32>> = vec![Box::new(f1), Box::new(f1)];
for f in arr {
println!("{}", (f)(1));
}
}
Alternatively, if you know that you only work with static functions, it is possible to store pointers to them directly, without using closure traits:
fn f1(i: i32) -> i32 { i * 2 }
fn f2(i: i32) -> i32 { i * 4 }
fn main() {
let arr: Vec<fn(i32) -> i32> = vec![f1, f2];
for f in &arr {
println!("{}", (f)(1));
}
}
While f1 and f2 actually have different incompatible types, they are automatically coerced to the general function pointer type fn(i32) -> i32 when used in appropriate context, like in the example above.
Because static functions don't have any environment, you can freely clone references to them and call them through any kind of reference. This is probably the way to go if you only need static functions.
This answer was updated for Rust 1.x; older versions of the answer remain in the edit history.

Resources