I've got a scenario looking like this:
struct Instance {
id: Option<String>,
}
struct Context {
instances: Vec<Instance>,
}
impl Context {
async fn filter_async(&self) -> Vec<String> {
self.instances.iter().filter_map(|x|x.id).collect()
}
fn filter(&self) -> Vec<String> {
self.instances.iter().filter_map(|x| x.id).collect()
}
}
With error message:
--> src/main.rs:41:46
|
41 | self.instances.iter().filter_map(|x| x.id).collect()
| ^^^^
| |
| move occurs because `x.id` has type `std::option::Option<std::string::String>`, which does not implement the `Copy` trait
| help: consider borrowing the `Option`'s content: `x.id.as_ref()`
I'm trying to figure out what it means. the filter function works just fine, but using the async functions yields a error message.
I'm curious about what's going on here. In the async func It wants to be able to Copy the x.id, this can however be solved though .clone().
Does this mean that the non-async function uses some form of memcpy or otherwise that can't be used in the async scope?
Related
I trying to implement a proxy in Rust, allowing me to read a model, but also to perform mutable operations. To avoid having two different implementations of the proxy (one mutable, one immutable), I made the proxy implementation generic.
I would like the proxy to create other instances of self, in different situations, and this is where I got a type mismatch.
The code below reproduces the problem I have:
use std::borrow::{Borrow, BorrowMut};
struct Model {
data: Vec<u32>,
}
impl Model {
fn get_proxy(&self) -> Proxy<&Model> {
Proxy::new(self)
}
fn get_proxy_mut(&mut self) -> Proxy<&mut Model> {
Proxy::new(self)
}
}
struct Proxy<M: Borrow<Model>> {
model: M
}
impl<M: Borrow<Model>> Proxy<M> {
fn new(model: M) -> Self {
Self {model}
}
fn get_another(&self) -> Proxy<M> {
// FIRST ERROR here
self.model.borrow().get_proxy()
}
}
impl<M: BorrowMut<Model>> Proxy<M> {
fn get_another_mut(&mut self) -> Proxy<M> {
// SECOND ERROR here
self.model.borrow_mut().get_proxy_mut()
}
}
The first compiler error looks like
error[E0308]: mismatched types
--> src\sandbox.rs:28:9
|
21 | impl<'m, M: Borrow<Model>> Proxy<M> {
| - this type parameter
...
26 | fn get_another(&self) -> Proxy<M> {
| -------- expected `Proxy<M>` because of return type
27 | // FIRST ERROR here
28 | self.model.borrow().get_proxy()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `M`, found `&Model`
|
= note: expected struct `Proxy<M>`
found struct `Proxy<&Model>`
Any idea how to fix the first error? (I assume the second one will be fixed in a similar way).
If I was to use this code on Actix Web 3 it would work, but I need to use the latest stable release... so 4^.
Here is the snippet in question (actually this is the entirety of my code):
use actix_web::{web, App, HttpResponse, HttpServer, ResponseError, Handler};
fn hello_world() -> HttpResponse {
HttpResponse::Ok().body("Hello, Mr. World") }
#[actix_web::main] async fn main() -> std::io::Result<()> {
HttpServer::new(move || App::new().route("hello", web::get().to(hello_world)))
.bind("0.0.0.0:8000")?
.run()
.await
}
Here is the error I get in version 4 or higher.
web::get().to(hello_world)))
| -- ^^^^^^^^^^^ the trait `Handler<_>` is not implemented for `fn() -> HttpResponse {hello_world}`
| |
| required by a bound introduced by this call
|
note: required by a bound in `Route::to`
--> /Users/xavierfontvillasenor/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-web-4.1.0/src/route.rs:211:12
|
211 | F: Handler<Args>,
| ^^^^^^^^^^^^^ required by this bound in `Route::to`
When I add the trait,
impl Handler<T> for HttpResponse {
type Output = ();
type Future = ();
fn call(&self, args: T) -> Self::Future {
todo!()
}
}
I get
impl Handler<T> for HttpResponse {
| - ^ not found in this scope
| |
| help: you might be missing a type parameter: `<T>`
This works in V.3 why not now? What can I do?
You are not meant to implement Handler yourself, the issue is that handlers are required to be async functions, see the docs for more details:
// 👇
async fn hello_world() -> HttpResponse {
HttpResponse::Ok().body("Hello, Mr. World")
}
Actix Web v4 removed the implementation of Future for HttpResponse causing this error. The compiler is correct but it's not the most useful error. TL;DR: all handlers must be async.
See the migration guide
There's a pattern I'm frequently encountering when writing async Rust code. Let's say I have a Foo struct (in real code, this could be something like a network client) and an async function that takes a reference to an instance of this struct:
struct Foo {
i: i32
}
async fn use_foo(foo: &Foo) -> () {
// do something with foo
}
Then, I want to run several use_foo concurrently, each with its own reference to a different Foo. A natural (but incorrect) way to do this would be:
use futures::stream::FuturesUnordered;
async fn foo_in_a_loop() {
let futures = FuturesUnordered::new();
for i in 0..10 {
let foo = Foo { i };
// does not compile: `foo` is dropped before the future is dropped
futures.push(use_foo(&foo));
}
}
which doesn't compile:
error[E0597]: `foo` does not live long enough
--> src/main.rs:53:30
|
53 | futures.push(use_foo(&foo));
| ^^^^ borrowed value does not live long enough
54 | }
| - `foo` dropped here while still borrowed
55 | }
| - borrow might be used here, when `futures` is dropped and runs the `Drop` code for type `FuturesUnordered`
|
= note: values in a scope are dropped in the opposite order they are defined
For more information about this error, try `rustc --explain E0597`
My question boils down to: what's the most idiomatic way to fix this error? I'd like to "force" use_foo to take ownership of the Foo instance.
Right now, I'm using a helper function that takes ownership of foo:
async fn use_foo_owned(foo: Foo) -> () {
use_foo(&foo).await
}
async fn foo_in_a_loop_owned() {
let futures = FuturesUnordered::new();
for i in 0..10 {
let foo = Foo { i };
futures.push(use_foo_owned(foo));
}
}
which does compile, but introducing an extra function just to please the borrow checker is clunky.
Note that sometimes use_foo may come from another crate and I may not be able to change its signature, but if there's an elegant solution that involves modifying use_foo, I'm interested too.
Use an async move {} block to create a future that takes ownership of foo and calls use_foo:
futures.push(async move { use_foo(&foo).await });
In the below example, I'm using an Arc to reference server state from a request handler, but the compiler make the closure an FnOnce. It feels like I'm doing the right thing in that each closure owns a strong reference to the state. Why doesn't this work? What options are there to make it work? Other questions like Share Arc between closures indicate something like this working, but I'm making the per-closure clones as shown and still getting an error.
#![feature(async_closure)]
#[derive(Default, Debug)]
struct State {}
impl State {
pub async fn exists(&self, key: &str) -> bool {
true
}
pub async fn update(&self, key: &str) {}
}
#[tokio::main]
async fn main() {
use warp::Filter;
use std::sync::Arc;
let state: Arc<State> = Arc::default();
let api = warp::post()
.and(warp::path("/api"))
.and(warp::path::param::<String>().and_then({
let state = Arc::clone(&state);
async move |p: String| {
let x = state.exists(&p);
if x.await {
Ok(p)
} else {
Err(warp::reject::not_found())
}
}
}))
.and_then({
let state = Arc::clone(&state);
async move |id: String| {
state.update(&id).await;
Result::<String, warp::Rejection>::Ok("".to_owned())
}
});
warp::serve(api).run(([127, 0, 0, 1], 0)).await;
}
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
--> src/main.rs:25:13
|
23 | .and(warp::path::param::<String>().and_then({
| -------- the requirement to implement `Fn` derives from here
24 | let state = Arc::clone(&state);
25 | async move |p: String| {
| _____________^^^^^^^^^^^^^^^^^^^^^^_-
| | |
| | this closure implements `FnOnce`, not `Fn`
26 | | let x = state.exists(&p);
27 | | if x.await {
28 | | Ok(p)
... |
31 | | }
32 | | }
| |_____________- closure is `FnOnce` because it moves the variable `state` out of its environment
Well, async closures are unstable, so that may be a bug. I think that when the async block captures the Arc it consumes it, so the closure can actually only be called once. I mean, an async closure is some kind of generator: each time you call it it constructs a future, and it is the future which keeps the captured values.
As a workaround you may write something like this:
let state = Arc::clone(&state);
move |p: String| {
let state = Arc::clone(&state);
async move {
let x = state.exists(&p);
//...
}
}
Doing another clone inside the closure but before the async block ensures that you can call the closure as many times as you need.
I would argue that actually Warp::Filter should accept a FnOnce to begin with, but I don't know warp enough to be sure.
This question already has answers here:
What do I have to do to solve a "use of moved value" error?
(3 answers)
What types are valid for the `self` parameter of a method?
(2 answers)
Closed 3 years ago.
It seems to be fine to modify a vector on its own, but as soon as it is wrapped in a struct, it can not be mutated by a method on the struct.
I've created a very simplified version of my use case below, in two versions, one with just a vector, and one with a struct.
Why is it that this code is fine:
struct Task {
foo: String,
}
fn main() {
let mut list_of_tasks = Vec::new();
loop {
list_of_tasks.push(Task {
foo: String::from("bar"),
});
}
}
But this is not:
struct Task {
foo: String,
}
struct ListOfTasks(pub Vec<Task>);
impl ListOfTasks {
fn push(mut self, task: Task) {
self.0.push(task);
}
}
fn main() {
let list_of_tasks = ListOfTasks(Vec::new());
loop {
list_of_tasks.push(Task {
foo: String::from("bar"),
});
}
}
The second example fails with:
error[E0382]: use of moved value: `list_of_tasks`
--> src/main.rs:17:9
|
14 | let list_of_tasks = ListOfTasks(Vec::new());
| ------------- move occurs because `list_of_tasks` has type `ListOfTasks`, which does not implement the `Copy` trait
...
17 | list_of_tasks.push(Task {
| ^^^^^^^^^^^^^ value moved here, in previous iteration of loop
I think I'm not understanding something about moving a struct that uses mut self, but can't find any obvious examples online of how to approach this.