FnOnce is not general enough

I started having an error out of no where saying

.any_method("/", upgrade_ws_with_req(handle
))
   |                                      ^^^^^^^^^^^^^^^^^^^ implem
entation of `std::ops::FnOnce` is not general enough
   |
   = note: closure with signature `fn(&'0 std::string::String) -> st
d::option::Option<std::collections::HashSet<i64>>` must implement `s
td::ops::FnOnce<(&std::string::String,)>`, for any lifetime `'0`...
   = note: ...but it actually implements `std::ops::FnOnce<(&std::st
ring::String,)>`

however the course of this error is a single variable like 5 calls deep and cant figure out whats going on


	pub async fn user_disconnected_cache_cleanup(&self, uid: &str)
	//{{{
	{
		//...
//orders_by_id:Arc<RwLock<HashMap<i64,Order>
		/* >>> */ let order_lock = self.orders_by_id.read().await; //if I comment out this particular line things compile fine
		//...
	} //}}}

Could you perhaps give a more complete version of the error message, as well as a more complete reproduction of the relevant source code? Error messages usually start with “error[…]: …”. And I don’t even see a closure in the source code.

thats the problem there's no closure when I delete that line everything compiles fine and that's the entire error message I am getting

Where’s the code that the error message references and how is it connected to the code you showed us?

Is upgrade_ws_with_req an ordinary function (item), or a closure? What type is handle? Is there something with a (&String) -> Option<HashSet<i64>> signature?

handle is a regular function

async fn handle(req: Request<Body>, ws: WebSocket)

and this is what upgrade_ws_with_req is

Is there nothing with a (&String) -> Option<HashSet<i64>> signature?

that seems to be the signature of HashMap::get

handle is responsible for calling the user_disconnected_cache_cleanup and again If I comment out that particular line things compile just fine

In case you mean HashMap::get, I don’t see the connection; that one has a different signature.

Assuming that upgrade_ws_with_req and handle are as you described, the error message does seem problematic/wrong/off.

In case it’s just the error location that’s completely off, given the fact that the let order_lock = self.orders_by_id.read().await; line seems to make a difference, what are …

… wait, if orders_by_id: Arc<RwLock<HashMap<i64,Order>>>, how do you “.await” a Result<RwLockReadGuard<'_, HashMap<…, …>>, …>?

thats a tokio Rwlock

ah… :sweat_smile:

that makes a lot of sense

Is this code open source? If yes, could you just share the whole thing as a branch on GitHub?

unfortunately its not it just started failing today and I didn't really change much I will try to rewind my steps to see what may have been causing once I have more info I will share more. Any ideas are also welcome tho :slight_smile: I first time see such a cryptic unhelpful message from the compiler. It's like core dumped

These errors can be very cryptic. Sometimes it's because of stuff like the future not being Send.

Are you sure that should be a Tokio mutex? Do you really need to hold it locked across an .await?

@alice whats the alternative ?

well, the problem in my case is that I do await things whilst holding the lock. also, I like not having to handle or think about the poisoned state of the lock

The reason I ask is that it's often possible to make a simple change so you don't need to await things while holding the lock. Using a blocking lock is a lot faster when it is possible.

You can avoid poisoning by using the parking_lot crate.

but in my case that defeats the purpose of the state if I release the lock before I have completed my async operations then some other operation could get a write lock on the thing and corrupt the state

Fair enough, then the answer is that you do need the Tokio mutex.

the only change between working and broken branch is that before the order to user relation was one to many not its order to user_account (many to many) and changes are as follows


and here the red one is the working version while green won't compile

@steffahn @alice I fixed it but I don't know why it works now If you have an explanation I'd be really grateful.
Basically, the issue was the line prior

		let order_ids_sent_to_user = accounts_of_user
			.iter()
			.map(|account_id| orders_sent_map.remove(account_id))
			.flatten()
			.flatten();
			//.collect::<Vec<_>>(); after adding this line error goes away.

Also collecting without the type hint collect it as HashSet which I noticed fails too

Thanks in advance :blush:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.