Skip to content

Instantly share code, notes, and snippets.

@roblabla
Last active July 17, 2019 18:58
Show Gist options
  • Save roblabla/588e31f63b1fb835da1b5063fe7029ae to your computer and use it in GitHub Desktop.
Save roblabla/588e31f63b1fb835da1b5063fe7029ae to your computer and use it in GitHub Desktop.
reproducer
[roblabla@roblab kfs]$ cargo script test.rs
Updating crates.io index
Compiling test v0.1.0 (/home/roblabla/.cargo/script-cache/file-test-5e1527e420b8259e)
error[E0308]: mismatched types
--> test.rs:18:5
|
18 | ForceSend(wrapper);
| ^^^^^^^^^ one type is more general than the other
|
= note: expected type `std::ops::FnOnce<(&mut Test, &mut [u8])>`
found type `for<'a> std::ops::FnOnce<(&'a mut Test, &'a mut [u8])>`
error: implementation of `std::ops::FnOnce` is not general enough
--> test.rs:18:5
|
18 | ForceSend(wrapper);
| ^^^^^^^^^
|
= note: `std::ops::FnOnce<(&'0 mut Test, &'0 mut [u8])>` would have to be implemented for the type `for<'a> fn(&'a mut Test, &'a mut [u8]) -> futures_core::future::future_obj::FutureObj<'a, std::result::Result<(), ()>> {Test::dispatch}`, for some specific lifetime `'0`
= note: but `std::ops::FnOnce<(&mut Test, &mut [u8])>` is actually implemented for the type `for<'a> fn(&'a mut Test, &'a mut [u8]) -> futures_core::future::future_obj::FutureObj<'a, std::result::Result<(), ()>> {Test::dispatch}`
error[E0308]: mismatched types
--> test.rs:18:5
|
18 | ForceSend(wrapper);
| ^^^^^^^^^ one type is more general than the other
|
= note: expected type `std::ops::FnMut<(&mut Test, &mut [u8])>`
found type `for<'a> std::ops::FnMut<(&'a mut Test, &'a mut [u8])>`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.
error: Could not compile `test`.
To learn more, run the command again with --verbose.
internal error: cargo failed with status 101
//! ```cargo
//! [package]
//! edition = "2018"
//!
//! [dependencies]
//! futures-preview = { version = "0.3.0-alpha.16", default-features = false, features = ["nightly", "alloc"] }
//! ```
#![feature(unboxed_closures, fn_traits)]
#![feature(async_await)]
use core::future::Future;
use futures::future::FutureObj;
struct ForceSend<T: Send>(T);
fn main() {
let wrapper = new_session_wrapper(Test(0), Test::dispatch);
ForceSend(wrapper);
}
struct Test(u8);
impl Test {
fn dispatch<'a>(&'a mut self, buf: &'a mut [u8]) -> FutureObj<'a, Result<(), ()>> {
FutureObj::new(Box::new(futures::future::lazy(|_| {
buf[0] = 1;
self.0 = 2;
Ok(())
})))
}
}
async fn new_session_wrapper<T, DISPATCH>(mut object: T, mut dispatch: DISPATCH) -> ()
where
DISPATCH: for<'b> FutureCallback<(&'b mut T, &'b mut [u8]), Result<(), ()>>,
DISPATCH: Unpin + Send + 'static,
T: Unpin + Send + 'static,
{
let mut buf = [0u8; 0x100];
ForceSend(buf);
dispatch.call((&mut object, &mut buf[..],)).await;
}
// BOILERPLATE: HRTB workaround
trait FutureCallback<T, O>: FnMut<T> {
type Ret: Future<Output = O> + Send;
fn call(&mut self, x: T) -> Self::Ret;
}
// Implement it for all FnMut with Ret = Output
impl<T, O, F: FnMut<T>> FutureCallback<T, O> for F
where
F::Output: Future<Output = O> + Send,
{
type Ret = F::Output;
fn call(&mut self, x: T) -> Self::Ret {
self.call_mut(x)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment