The Iterator trait's method any takes a parameter implementing FnMut trait.
Here's the definiton
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn any<F>(&mut self, f: F) -> bool
where
Self: Sized,
F: FnMut(Self::Item) -> bool,
{
#[inline]
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> {
move |(), x| {
if f(x) { ControlFlow::BREAK } else { ControlFlow::CONTINUE }
}
}
self.try_fold((), check(f)) == ControlFlow::BREAK
}
I think the rule of FnMut is: The closure captures variables by mutable reference.
But the following code goes wrong because of "use of moved value: rust".
This means the variable rust has been moved into the closure, which has conflicts with the rule of FnMut trait.
// Situation 1
let rust = String::from("rust");
let list: Vec<String> = vec![String::from("rust")];
list.into_iter().any(move |s| s == rust);
dbg!(rust); // error here
However, the following code is also refused by the compiler due to the rule of FnMut trait.
// Situation 2
let rust = String::from("rust");
let list: Vec<String> = vec![String::from("rust")];
list.into_iter().any(move |s| {
let temp = rust; // error here
s == temp
});
So my question is, why there are different behaviors about the FnMut trait between these two situations?
I think the second situation is easy to understand. But why in the first situation, the captured variable will be consumed?
The variable has been moved into the closure because you used the move keyword. It has nothing to do with it being a FnMut.
The second code block produces an error because the closure might be called multiple times (since it's constrained to be FnMut), but the line let temp = rust; moves that variable again, into a variable that is dropped within the function body. This means that the environment of the closure would be invalid if it was ever called again. All functions and closures implement FnOnce, but this one can only implement FnOnce - i.e. it cannot implement Fn or FnMut.
It's not FnMut, it's move. The move keyword in move |s| causes captured variables to be moved into the closure. Leave it off to use the default capture mode, by reference:
let rust = String::from("rust");
let list: Vec<String> = vec![String::from("rust")];
list.into_iter().any(|s| s == rust);
dbg!(rust);
Playground
Related
Rust allows assigning references with a higher level of indirection to references with a lower level of indirection. For instance, the compiler allows assigning a &&&&&& to a &:
fn main() {
let mut some_number = 5;
// assign an &&&&&&i32 to an &i32, which works.
let reference : &i32 = &&&&&&some_number;
}
This also works for function parameters:
fn main() {
let num = 5;
// ref1 is an &&i32
let ref1 = &#
// Pass an &&i32 to a function parameter, which itself is an &i32 (works)
func(ref1);
}
fn func(test: &i32) {
println!("^^^^ This works!");
}
I've learned that this works because of automatic dereferencing, which allows the Rust compiler to dereference a type as much as it needs to match some other type (please correct me if I'm wrong on this).
However, Rust doesn't seem to allow assigning lower-indirection references to higher-indirection references:
fn main() {
let num = 5;
// Try assigning an &i32 to an &&i32 (error)
let ref1 : &&i32 = #
}
This results in an expected &i32, found integer compiler error. We get a similar compiler error when testing this with function parameters:
fn main() {
let num = 5;
// ref1 is an &&&i32
let ref1 = &&#
// Try passing an &&&i32 to a function parameter of type &&&&&i32 (error)
func(ref1);
}
fn func(test: &&&&&i32) {
println!("^^^^^^^^ This does not work!")
}
Here, we get a mismatched types error as well. Something I'm curious about, however, is that the compiler output isn't exactly what we expect. Rather than expected &&&&&i32, found &&&i32, the compiler error is expected &&i32, found integer. It seems that the compiler dereferenced both references until one was no longer a reference - why does it dereference both references? I thought it only dereferenced whatever was being passed to the function.
Overall, my main question is
Why, exactly, should assigning lower-indirection to higher-indirection references be disallowed when assigning higher-indirection to lower-indirection references is allowed? What is so different about these two things, that their behaviors must be different as well?
&&T can be coerced to &T because of deref coercion ("&T or &mut T to &U if T implements Deref<Target = U>") and the impl Deref<Target = T> for &T the other way is not possible because there exists no impl Deref<Target = &T> for T.
By repeatet application &&&&&&T can be coerced to &T
As to why one is allowed while the other isn't well if implicit referencing was allowed everywhere tracking ownership would be even harder than it currently is, we have this problem already with auto-referencing of method receivers.
let s = String::from("Hello");
my_fun(s);
The question "Does s get moved?" can't be answered without looking at the definition of my_fun if we allow automatic referencing.
What is the effect of writing the value of the option when returning the closure?
let value = Some(0);
let closure = if value.is_some() {
|value: i32| false
} else {
|value: i32| true
};
The code above does not produce a compilation error
However, the code below has a compilation error What's the reason?
let closure = if let Some(option_value) = value {
|value: i32| option_value == value
} else {
|value: i32| true
};
They're all different types
`if` and `else` have incompatible types
no two closures, even if identical, have the same type
consider boxing your closure and/or using it as a trait object
Box is a solution. But I don't know the difference yet
let closure = if let Some(option_value) = value {
Box::new(move |value: i32| option_value == value)
} else {
Box::new(|value: i32| true)
};
Box is a solution. But I don't know the difference yet
As baseline, every function (anonymous or not) has its own concrete type, different from all others.
However named functions and non-closure anonymous functions can be coerced to "function pointers" fn(args...) -> ret.
That is what happens in your first snippet, if you use "the unit trick":
let _: () = closure;
to know what rustc has decided the concrete type of closure is, it tells you:
found fn pointer `fn(i32) -> bool`
so because both anonymous functions are static (they don't actually close over anything), the compiler converted both into function pointers.
That doesn't work with the second snippet, because the first branch creates an actual closure, which can't be converted to a function pointer (because it's not just a function, it's also data). Hence type mismatch.
Boxing works, because it allows the creation of dynamically dispatched trait objects of type
Box<dyn Fn(i32) -> bool>
which are compatible.
I think your mistake is that you assumed the type of both Closures is
Fn(i32) -> bool
But that is a trait, not a type, each closure has it is own type, which implements the above trait.
T: impl Fn(i32) -> bool
Box solves that issue as the type for both becomes Box<dyn Fn(i32)->bool>
I'm learning Rust's async/await feature, and stuck with the following task. I would like to:
Create an async closure (or better to say async block) at runtime;
Pass created closure to constructor of some struct and store it;
Execute created closure later.
Looking through similar questions I wrote the following code:
use tokio;
use std::pin::Pin;
use std::future::Future;
struct Services {
s1: Box<dyn FnOnce(&mut Vec<usize>) -> Pin<Box<dyn Future<Output = ()>>>>,
}
impl Services {
fn new(f: Box<dyn FnOnce(&mut Vec<usize>) -> Pin<Box<dyn Future<Output = ()>>>>) -> Self {
Services { s1: f }
}
}
enum NumberOperation {
AddOne,
MinusOne
}
#[tokio::main]
async fn main() {
let mut input = vec![1,2,3];
let op = NumberOperation::AddOne;
let s = Services::new(Box::new(|numbers: &mut Vec<usize>| Box::pin(async move {
for n in numbers {
match op {
NumberOperation::AddOne => *n = *n + 1,
NumberOperation::MinusOne => *n = *n - 1,
};
}
})));
(s.s1)(&mut input).await;
assert_eq!(input, vec![2,3,4]);
}
But above code won't compile, because of invalid lifetimes.
How to specify lifetimes to make above example compile (so Rust will know that async closure should live as long as input). As I understand in provided example Rust requires closure to have static lifetime?
Also it's not clear why do we have to use Pin<Box> as return type?
Is it possible somehow to refactor code and eliminate: Box::new(|arg: T| Box::pin(async move {}))? Maybe there is some crate?
Thanks
Update
There is similar question How can I store an async function in a struct and call it from a struct instance?
. Although that's a similar question and actually my example is based on one of the answers from that question. Second answer contains information about closures created at runtime, but seems it works only when I pass an owned variable, but in my example I would like to pass to closure created at runtime mutable reference, not owned variable.
How to specify lifetimes to make above example compile (so Rust will know that async closure should live as long as input). As I understand in provided example Rust requires closure to have static lifetime?
Let's take a closer look at what happens when you invoke the closure:
(s.s1)(&mut input).await;
// ^^^^^^^^^^^^^^^^^^
// closure invocation
The closure immediately returns a future. You could assign that future to a variable and hold on to it until later:
let future = (s.s1)(&mut input);
// do some other stuff
future.await;
The problem is, because the future is boxed, it could be held around for the rest of the program's life without ever being driven to completion; that is, it could have 'static lifetime. And input must obviously remain borrowed until the future resolves: else imagine, for example, what would happen if "some other stuff" above involved modifying, moving or even dropping input—consider what would then happen when the future is run?
One solution would be to pass ownership of the Vec into the closure and then return it again from the future:
let s = Services::new(Box::new(move |mut numbers| Box::pin(async move {
for n in &mut numbers {
match op {
NumberOperation::AddOne => *n = *n + 1,
NumberOperation::MinusOne => *n = *n - 1,
};
}
numbers
})));
let output = (s.s1)(input).await;
assert_eq!(output, vec![2,3,4]);
See it on the playground.
#kmdreko's answer shows how you can instead actually tie the lifetime of the borrow to that of the returned future.
Also it's not clear why do we have to use Pin as return type?
Let's look at a stupidly simple async block:
async {
let mut x = 123;
let r = &mut x;
some_async_fn().await;
*r += 1;
x
}
Notice that execution may pause at the await. When that happens, the incumbent values of x and r must be stored temporarily (in the Future object: it's just a struct, in this case with fields for x and r). But r is a reference to another field in the same struct! If the future were then moved from its current location to somewhere else in memory, r would still refer to the old location of x and not the new one. Undefined Behaviour. Bad bad bad.
You may have observed that the future can also hold references to things that are stored elsewhere, such as the &mut input in #kmdreko's answer; because they are borrowed, those also cannot be moved for the duration of the borrow. So why can't the immovability of the future similarly be enforced by r's borrowing of x, without pinning? Well, the future's lifetime would then depend on its content—and such circularities are impossible in Rust.
This, generally, is the problem with self-referential data structures. Rust's solution is to prevent them from being moved: that is, to "pin" them.
Is it possible somehow to refactor code and eliminate: Box::new(|arg: T| Box::pin(async move {}))? Maybe there is some crate?
In your specific example, the closure and future can reside on the stack and you can simply get rid of all the boxing and pinning (the borrow-checker can ensure stack items don’t move without explicit pinning). However, if you want to return the Services from a function, you'll run into difficulties stating its type parameters: impl Trait would normally be your go-to solution for this type of problem, but it's limited and does not (currently) extend to associated types, such as that of the returned future.
There are work-arounds, but using boxed trait objects is often the most practical solution—albeit it introduces heap allocations and an additional layer of indirection with commensurate runtime cost. Such trait objects are however unavoidable where a single instance of your Services structure may hold different closures in s1 over the course of its life, where you're returning them from trait methods (which currently can’t use impl Trait), or where you're interfacing with a library that does not provide any alternative.
If you want your example to work as is, the missing component is communicating to the compiler what lifetime associations are allowed. Trait objects like dyn Future<...> are constrained to be 'static by default, which means it cannot have references to non-static objects. This is a problem because your closure returns a Future that needs to keep a reference to numbers in order to work.
The direct fix is to annotate that the dyn FnOnce can return a Future that can be bound to the life of the first parameter. This requires a higher-ranked trait bound and the syntax looks like for<'a>:
struct Services {
s1: Box<dyn for<'a> FnOnce(&'a mut Vec<usize>) -> Pin<Box<dyn Future<Output = ()> + 'a>>>,
}
impl Services {
fn new(f: Box<dyn for<'a> FnOnce(&'a mut Vec<usize>) -> Pin<Box<dyn Future<Output = ()> + 'a>>>) -> Self {
Services { s1: f }
}
}
The rest of your code now compiles without modification, check it out on the playground.
This question already has answers here:
Temporarily move out of borrowed content
(3 answers)
Closed 1 year ago.
I'm working with two separate functions.
The first one takes an owned instance of a structure then returns it.
The second one takes a mutable reference but needs to use the first function.
// This structure is not `Clone`.
struct MyStruct;
fn take_owned(s: MyStruct) -> MyStruct {
// Do things
s
}
fn take_mut(s: &mut MyStruct) {
*s = take_owned(s /* problem */);
}
I thought about a solution but I'm not sure it's sound:
use std::ptr;
// Temporarily turns a mutable reference into an owned value.
fn mut_to_owned<F>(val: &mut MyStruct, f: F)
where
F: FnOnce(MyStruct) -> MyStruct,
{
// We're the only one able to access the data referenced by `val`.
// This operation simply takes ownership of the value.
let owned = unsafe { ptr::read(val) };
// Do things to the owned value.
let result = f(owned);
// Give the ownership of the value back to its original owner.
// From its point of view, nothing happened to the value because we have
// an exclusive reference.
unsafe { ptr::write(val, result) };
}
Using this function, I can do that :
fn take_mut(s: &mut MyStruct) {
mut_to_owned(s, take_owned);
}
Is this code sound? If not, is there a way to safely do this?
Someone has already implemented what you're looking for, in the crate named take_mut.
Function take_mut::take
pub fn take<T, F>(mut_ref: &mut T, closure: F)
where
F: FnOnce(T) -> T,
Allows use of a value pointed to by &mut T as though it was owned, as long as a T is made available afterwards.
...
Will abort the program if the closure panics.
Function take_mut::take_or_recover
pub fn take_or_recover<T, F, R>(mut_ref: &mut T, recover: R, closure: F)
where
F: FnOnce(T) -> T,
R: FnOnce() -> T,
Allows use of a value pointed to by &mut T as though it was owned, as long as a T is made available afterwards.
...
Will replace &mut T with recover if the closure panics, then continues the panic.
The implementation is essentially what you have, plus panic handling as described.
I have a petgraph::Graph structure onto which I have imposed a tree structure by giving every node weight a parent_edge_idx which is an Option<EdgeIdx> of the edge that connects from its parent to itself.
I need to iterate over a node's children. I need the edge weight of the connecting edge and the node weight of the child.
I wanted to factor that iteration into a helper function that returns a reference to an Iterator<Item = (EdgeIdx, NodeIdx)>. I want to do this cost-free; since I have to borrow self.search_tree in order to do this, the iterator is only valid for the lifetime of self.
Is this a reasonable function to want to write?
Is it possible to write this function?
Any gated features are ok; I'm on nightly.
fn children<'a>(
&'a mut self,
node_idx: NodeIdx,
) -> &'a impl Iterator<Item = (EdgeIdx, NodeIdx)> {
&self.search_tree.neighbors(node_idx).map(|child_idx| {
let node = self.search_tree.node_weight(child_idx).unwrap();
let edge_idx = node.parent_edge_idx.unwrap();
(edge_idx, child_idx)
})
}
How to return an iterator is already covered in this question.
Note that you don't need to return a reference: you want to return an iterator value directly, so if we remove the first & in both the method body and the return type, that's closer to what we need.
We will use impl Iterator so that we don't have to name the actual iterator type exactly. Just note (code below) that we need to use the impl Iterator<..> + 'a syntax, which means that the (anonymous) iterator contains references valid to use for at least the lifetime 'a.
We can't use &mut self here! Note that we need to borrow self.search_tree twice: once for the .neighbors() iterator and once for the self.search_tree that's used in the map closure. Multiple borrowing is incompatible with mutable references.
We put move as the capture mode on the closure, so that it captures the self reference directly, and not by reference (this is important so that we can return the iterator and the closure.
Petgraph specific, but we replace g.node_weight(node_index).unwrap() with just &g[node_index] which is equivalent, but the latter is easier to read.
Here is a reproduction of your code, but with modifications along 1-5 to make it compile:
#![feature(conservative_impl_trait)]
extern crate petgraph;
use petgraph::Graph;
use petgraph::graph::{NodeIndex, EdgeIndex};
struct Foo {
search_tree: Graph<Node, i32>,
}
struct Node {
parent_edge_idx: Option<EdgeIndex>,
}
impl Foo {
fn children<'a>(&'a self, node_idx: NodeIndex)
-> impl Iterator<Item = (EdgeIndex, NodeIndex)> + 'a
{
self.search_tree.neighbors(node_idx).map(move |child_idx| {
let node = &self.search_tree[child_idx];
let edge_idx = node.parent_edge_idx.unwrap();
(edge_idx, child_idx)
})
}
}