Cannot move out of borrowed context [duplicate] - rust

This question already has an answer here:
Cannot move out of borrowed content / cannot move out of behind a shared reference
(1 answer)
Closed 4 years ago.
I have a very simple piece of code that I cannot get to compile:
struct X;
struct A {
field: Option<Box<X>>,
}
impl A {
pub fn get_field(&self) -> Option<&X> {
return self.field.map(|value| &*value);
}
}
error[E0507]: cannot move out of borrowed content
--> src/lib.rs:9:16
|
9 | return self.field.map(|value| &*value);
| ^^^^ cannot move out of borrowed content
error[E0597]: `*value` does not live long enough
--> src/lib.rs:9:40
|
9 | return self.field.map(|value| &*value);
| ^^^^^-
| | |
| | borrowed value only lives until here
| borrowed value does not live long enough
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 8:5...
--> src/lib.rs:8:5
|
8 | / pub fn get_field(&self) -> Option<&X> {
9 | | return self.field.map(|value| &*value);
10| | }
| |_____^
I don't really understand why this doesn't work.

I don't really understand why this doesn't work.
Your code defined a struct A that may or may not hold a X in the heap (not in the stack).
In the method get_field you were given a reference to the struct, but you want to get a reference to the inner X, if possible.
The above are concluded only by looking at the function signatures and struct definition of A.
Looking into the function body, self.field is of type Option<_>, and map is its method. Look at the documentation for Option::map:
pub fn map<U, F>(self, f: F) -> Option<U>
where
F: FnOnce(T) -> U,
Maps an Option<T> to Option<U> by applying a function to a contained value.
It accepts a closure that can only run once, accepts a Box<X> in your case, then according to your function return type it should return &X. It looks like a perfect match at first glance since if value: Box<X> then *value: X and &*value: &X, but it does not compile! What's wrong?
If you look more carefully at the signature of map you see it has 2 parameters, not one. The first parameter is the "method receiver" self and its type is Self.
In Rust, this means this call will need to consume the method receiver; the object you used to call the method would be no longer valid after this call.
However, your get_field method is not allowed to remove the method receiver self.field: self is only a reference to A, so self.field is also just a reference . You then cannot call map to consume self.field.
The solution, is to use as_ref:
pub fn as_ref(&self) -> Option<&T>
Converts from Option<T> to Option<&T>.
Although it says converts from Option<T>, but from the signature you can see it accepts &Option<T>, so it just moves the outside & inside. Now you can use map.
pub fn get_field(&self) -> Option<&X> {
return self.field.as_ref().map(|value| &*value);
}
Now it works.

Related

Why do I get a "closure implements `FnMut`, so references to captured variables can't escape the closure" here?

I have a generic Interface trait. Interface has a method, which will be called using dynamic dispatch. Specifically, I'll be passing around Rc<RefCell<dyn Interface>>.
I have a use case where I need to wrap a call to method inside a closure. The desired behavior is that calling the closure with input would be identical to calling obj.method with input where obj implements Interface.
The following is my attempt so far.
use std::cell::RefCell;
use std::rc::Rc;
pub trait Interface<'p, T> {
fn method<'s: 'p>(&'p self, input: &'s str) -> T;
}
fn wrap_interface_with_closure<'p, 's: 'p, T: 'p>(
instance: Rc<RefCell<dyn Interface<'p, T>>>,
) -> impl FnMut(&'s str) -> T + 'p {
move |input| (*instance).borrow().method(input)
}
This gives me the following error:
error[E0716]: temporary value dropped while borrowed
|
13 | instance: Rc<RefCell<dyn Interface<'p, T>>>,
| -------- lifetime `'2` appears in the type of `instance`
14 | ) -> impl FnMut(&'s str) -> T + 'p {
15 | move |input| (*instance).borrow().method(input)
| ^^^^^^^^^^^^^^^^^^^^--------------
| | |
| | temporary value is freed at the end of this statement
| creates a temporary which is freed while still in use
| argument requires that borrow lasts for `'2`
error: lifetime may not live long enough
|
13 | instance: Rc<RefCell<dyn Interface<'p, T>>>,
| -------- lifetime `'2` appears in the type of `instance`
14 | ) -> impl FnMut(&'s str) -> T + 'p {
15 | move |input| (*instance).borrow().method(input)
| ------------ ^^^^^^^^ closure capture requires that `'1` must outlive `'2`
| |
| lifetime `'1` represents this closure's body
|
= note: closure implements `FnMut`, so references to captured variables can't escape the closure
error: aborting due to 2 previous errors; 2 warnings emitted
When it says closure implements FnMut, so references to captured variables can't escape the closure which captured variable is it talking about? Is it saying that instance is escaping? Does it mean that the borrow is escaping?
Your trait requires &'p self, i.e. the reference to self must be the same as 'p. Inside your closure you call borrow():
(*instance).borrow()
You obtain a reference to the Interface, whose lifetime lasts only throughout the closure ('1). However, your trait definition requires that the lifetime of self be 'p:
fn method<'s: 'p>(&'p self, input: &'s str) -> T;
So, when you call .method() in your closure, the lifetime of self will be '1 (valid inside the closure), which doesn't live long enough to satisfy the lifetime 'p from your parameter. You can fix this by removing the requirement for self:
fn method<'s: 'p>(&self, input: &'s str) -> T;
You can still be sure that input outlives your instance, since 's :'p is part of your wrap_interface_with_closure function.

Why does moving a disjoint field capture into a closure differ when the type is a value vs a reference?

As explained in Why is the move keyword needed when returning a closure which captures a Copy type? and How to copy instead of borrow an i64 into a closure in Rust?, if a closure captures a type that implements Copy, we need to use the move keyword to eagerly copy the value:
fn use_move_to_copy_into_closure() -> impl FnOnce(i32) -> bool {
let captured = 0;
move |value| value > captured
}
As of Rust 2021, disjoint capture in closures means that only the specific fields used in a closure are captured by the closure:
struct Wrapper(i32);
fn edition_2021_only_captures_specific_fields(captured: Wrapper) -> impl FnOnce(i32) -> bool {
let ret = move |value| value > captured.0;
drop(captured); // fails in 2015, 2018, succeeds in 2021
ret
}
If I capture a Copy field belonging to a reference, however, the field is not copied:
struct Wrapper(i32);
fn capturing_a_field_of_a_reference(captured: &Wrapper) -> impl FnOnce(i32) -> bool {
move |value| value > captured.0
}
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> src/lib.rs:15:60
|
15 | fn capturing_a_field_of_a_reference(captured: &Wrapper) -> impl FnOnce(i32) -> bool {
| -------- ^^^^^^^^^^^^^^^^^^^^^^^^
| |
| hidden type `[closure#src/lib.rs:16:5: 16:36]` captures the anonymous lifetime defined here
|
help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
|
15 | fn capturing_a_field_of_a_reference(captured: &Wrapper) -> impl FnOnce(i32) -> bool + '_ {
| ++++
I expected that the field .0 would be copied in, just like in the unwrapped i32 or the owned Wrapper cases. What causes this difference?
move captures the environment by value, but things in the environment that are references remain references -- the references are captured by value.
Put another way, move closures only try to move values, because otherwise there wouldn't be a way to simultaneously capture some things by value and some things by reference. For example, it's a common pattern to do this when dealing with threads in e.g. crossbeam. Assume these structs:
#[derive(Clone)]
struct Foo;
impl Foo {
pub fn baz(&mut self, _: i32) {}
}
struct Bar(pub i32);
And this snippet:
let foo = Foo;
let bar = Bar(0);
{
let mut foo = foo.clone();
let bar = &bar;
s.spawn(move |_| {
foo.baz(bar.0);
});
}
Here the closure takes ownership of the clone of foo but references bar.0. This is true even if the type of bar.0 is Copy.
If it didn't work this way, there would be no way to express that the closure should own the foo clone, but borrow the copyable value bar.0.
Remember that implementing Copy on a type only means that an attempt to move a value of that type will instead copy. Since captured is a reference in your third example, capturing captured.0 doesn't attempt to move the i32 like it does in your second example where you have an owned value, and if a move isn't attempted then no copy can happen.
It's not a question of whether the copy occurs, but when it occurs. The copy only happens when the closure is called, not when it's defined (how could it be -- a captured hasn't been provided yet). Since the closure outlives the function call, it needs to know that its reference to captured will be valid when it's actually called precisely so that it has something to copy. Therefore it needs to be annotated with a lifetime tying it to the lifetime of captured. Thanks to lifetime inference, it's sufficient to simply add '_ to the impl instead of needing to explicitly write fn capturing_a_field_of_a_reference<'a>(captured: &'a Wrapper) -> impl 'a + FnOnce(i32) -> bool.

Why is "the temporary is part of an expression at the end of a block" an error?

This is likely a textbook case of me not understanding some of the technicalities of the borrow checker, but it would be nice if someone could clear this up for me.
I have this (incredibly simplified) chunk of code, which compiles perfectly fine.
pub struct Example(pub Vec<String>);
impl Example {
pub fn iter(&self) -> impl Iterator<Item=&String> {
self.0.iter()
}
}
pub fn some_condition(_: &str) -> bool {
// This is not important.
return false;
}
pub fn foo() -> bool {
let example = Example(vec!("foo".to_owned(), "bar".to_owned()));
let mut tmp = example.iter();
tmp.all(|x| some_condition(x))
}
pub fn main() {
println!("{}", foo());
}
However, the first thing that I tried (which, in my mind, should be equivalent to the above), was eliding the temporary variable tmp altogether, as follows
pub fn foo() -> bool {
let example = Example(vec!("foo".to_owned(), "bar".to_owned()));
example.iter().all(|x| some_condition(x))
}
But this version produces the following error.
error[E0597]: `example` does not live long enough
--> so_temporary.rs:23:3
|
23 | example.iter().all(|x| some_condition(x))
| ^^^^^^^-------
| |
| borrowed value does not live long enough
| a temporary with access to the borrow is created here ...
24 | }
| -
| |
| `example` dropped here while still borrowed
| ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `impl std::iter::Iterator`
|
= note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
Now, obviously, the note at the end of the error is an excellent suggestion, and it's why I introduced the temporary to fix the problem. But I don't understand why that fixes the problem. What's different about the lifetimes of my tmp variable versus example.iter() embedded into the expression directly, that makes one work and one fail?
This has essentially the same answer as Why do I get "does not live long enough" in a return value? and its somewhat explained in the error itself, but I'll elaborate. This behavior is the same with a normal block expression:
pub struct Example(pub Vec<String>);
impl Example {
pub fn iter(&self) -> impl Iterator<Item=&String> {
self.0.iter()
}
}
pub fn main() {
let foo = {
let example = Example(vec!("foo".to_owned(), "".to_owned()));
example.iter().all(String::is_empty)
};
println!("{}", foo);
}
error[E0597]: `example` does not live long enough
--> src/main.rs:12:9
|
12 | example.iter().all(String::is_empty)
| ^^^^^^^-------
| |
| borrowed value does not live long enough
| a temporary with access to the borrow is created here ...
13 | };
| -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `impl Iterator`
| |
| `example` dropped here while still borrowed
|
= note: the temporary is part of an expression at the end of a block;
consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block
|
12 | let x = example.iter().all(String::is_empty); x
| ^^^^^^^ ^^^
The scope of temporary values is often the statement in which they were created. In the code above example is a variable and it is destroyed at the end of the block. However, example.iter() creates a temporary impl Iterator and its temporary scope is the full let foo = ... statement. So the steps when evaluating this are:
evaluate the result of example.iter().all(...)
drop example
assign result to foo
drop impl Iterator
You can probably see where this can go wrong. The reason introducing a variable works is because it forces any temporaries to be dropped sooner. The case is slightly different when talking about functions, but the effect is the same:
Temporaries that are created in the final expression of a function body are dropped after any named variables bound in the function body, as there is no smaller enclosing temporary scope.
Regarding the comments:
The reason it works when impl Iterator is replaced with std::slice::Iter<'_, i32> (in pretzelhammer's example) is because the drop checker knows that slice::Iter doesn't access example on drop whereas it has to assume that impl Iterator does.
The reason it works with fn my_all(mut self, ...) (in Peter Hall's example) is because all takes the iterator by reference but my_all takes it by value. The temporary impl Iterator is consumed and destroyed before the end of the expression.
From looking at various Rust issues relating to this, its clear that some would consider this a bug. Its definitely not obvious that { ...; EXPR } and { ...; let x = EXPR; x } could be different. However, since diagnostics and documentation have been added to reinforce and explain this behavior, I have to assume these temporary scoping rules allow for more reasonable code than not.

Trouble with Rust Lifetime in Generic function [duplicate]

This question already has answers here:
How to fix lifetime error when function returns a serde Deserialize type?
(2 answers)
Closed 3 years ago.
I have a simple function that I want to make generic, in rust. I am getting a lifetime error. I am still getting the hang of the lifetime side of rust.
The function simply converts 1 struct into another using serde's serialization.
Here is a a rust playground with the full simple scenario.
Code:
pub fn convert<'de: 'a, 'a, T>(from: &'a Left, print: bool) -> (T, &'a Left)
where
T: Deserialize<'de> + std::fmt::Debug {
let serialized = serde_json::to_string(&from);
let serialized = serialized.unwrap();
let deserialized: T;
{
let deserialized_raw = serde_json::from_str(&serialized);
deserialized = deserialized_raw.unwrap();
}
if print {
println!("-------------A-----------------------------------");
println!("serialized = {}", &serialized);
println!("--------------B----------------------------------");
println!("deserialized = {:?}", deserialized);
println!("--------------C----------------------------------");
};
(deserialized, from)
}
Error:
error[E0597]: `serialized` does not live long enough
--> src/main.rs:38:49
|
30 | pub fn convert<'de: 'a, 'a, T>(from: &'a Left, print: bool) -> (T, &'a Left)
| --- lifetime `'de` defined here
...
38 | let deserialized_raw = serde_json::from_str(&serialized);
| ---------------------^^^^^^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `serialized` is borrowed for `'de`
...
49 | }
| - `serialized` dropped here while still borrowed
I tried this a few ways with and without lifetimes. I tried adding blocks to see if that changes things with no luck.
Any thoughts on what I am doing wrong?
Edited:
- Added the full compiler error output
To the compiler, lifetime parameters always represent lifetimes that live strictly longer than the function call. However, here you're trying to use a local variable and claim it has lifetime 'de, which is impossible because it's a local variable, thus it has a lifetime shorter than the function call.
In order to mix lifetime parameters in traits with local variables, we must use higher-rank trait bounds. We want T to implement Deserialize<'de> for every lifetime 'de (not just one specific lifetime chosen by the caller). This is written like this (note that we can now elide the 'a lifetime):
pub fn convert<T>(from: &Left, print: bool) -> (T, &Left)
where
T: for<'de> Deserialize<'de> + std::fmt::Debug
{
// no changes here
}

How to create an iterator that allows mapping indices to mutable items in a slice [duplicate]

This question already has answers here:
How do I write an iterator that returns references to itself?
(4 answers)
Simultaneous mutable access to arbitrary indices of a large vector that are guaranteed to be disjoint
(5 answers)
How can I create my own data structure with an iterator that returns mutable references?
(1 answer)
Closed 3 years ago.
I have a slice of items and a slice of indices into the first slice, essentially giving me a sub-group of items that I want to modify. To iterate over the items and manipulate them I can create the following helper function.
fn process_things_by_index_loop<T>(things: &mut [T], indices: &[usize], f: &dyn Fn(&mut T)) {
for &ix in indices {
let t = &mut things[ix];
f(t);
}
}
This works fine, but I would actually just like to get an iterator over the items so I can apply, e.g., a filter to them before further processing.
It looks like this could just be a mapping of indices to items like so:
fn iterate_thigns<'a, T>(
things: &'a mut [T],
indices: &'a [usize],
) -> impl Iterator<Item = &'a mut T> {
indices.iter().map(|&ix| -> &mut T { &mut things[ix] })
}
This can't work of course, since I could have the same index twice in the indices slice and when collecting the iterator I would create two mutable references to the same item. So this gives appropriately a life-time error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src\main.rs:4:47
|
4 | indices.iter().map(|&ix|-> &mut T { &mut things[ix]})
| ^^^^^^^^^^
|
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src\main.rs:4:47
|
4 | indices.iter().map(|&ix|-> &mut T { &mut things[ix]})
| ^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 4:24...
--> src\main.rs:4:24
|
4 | indices.iter().map(|&ix|-> &mut T { &mut things[ix]})
| ^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src\main.rs:4:47
|
4 | indices.iter().map(|&ix|-> &mut T { &mut things[ix]})
| ^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 3:19...
--> src\main.rs:3:19
|
3 | fn iterate_thigns<'a, T>(things: &'a mut [T], indices: &'a [usize]) -> impl Iterator<Item=&'a mut T>{
| ^^
= note: ...so that the types are compatible:
expected &mut T
found &'a mut T
This also means the return type probably can't be a simple Iterator at all.
This issues seems also related to this blog post from 2013 on "Iterators yielding mutable references", which states that no standard solutions for this pattern exist yet.
There is also a related question asking about mutable multi threaded access to the content of a vector, but I am really interested in a single threaded, iterator-like solution, which might even allow indices to repeat.
So, is there something that enables an iterator-like interface for sequential iteration of the items indicated by the indices?

Resources