我是否可以将函数参数的Send
特征传播到其返回类型,以便返回类型为impl Send
当且仅当参数为?
Details:个
异步函数有一个很好的功能.如果可以的话,它返回的Future
自动是Send
.在下面的示例中,如果函数的输入是Send
,则该函数将创建一个等于Send
的Future
.
struct MyStruct;
impl MyStruct {
// This async fn returns an `impl Future<Output=T> + Send` if `T` is Send.
// Otherwise, it returns an `impl Future<Output=T>` without `Send`.
async fn func<T>(&self, t: T) -> T {
t
}
}
fn assert_is_send(_v: impl Send) {}
fn main() {
// This works
assert_is_send(MyStruct.func(4u64));
// And the following correctly fails
assert_is_send(MyStruct.func(std::rc::Rc::new(4u64)));
}
现在,我想将这样的函数转移到特征中,这需要使用async-特征(这是一些代码生成器,它有效地将我的async fn
写成返回Pin<Box<dyn Future>>
的函数)或手动执行类似的操作.有没有办法以一种方式来保留这种自动发送行为,即如果T
是Send
,则返回的Future
是Send
?下面的示例将其实现为两个单独的函数:
use std::pin::Pin;
use std::future::Future;
struct MyStruct;
impl MyStruct {
fn func_send<T: 'static + Send>(&self, t: T) -> Pin<Box<dyn Future<Output = T> + Send>> {
Box::pin(async{t})
}
fn func_not_send<T: 'static>(&self, t: T) -> Pin<Box<dyn Future<Output = T>>> {
Box::pin(async{t})
}
}
fn assert_is_send(_v: impl Send) {}
fn main() {
// This works
assert_is_send(MyStruct.func_send(4u64));
// And the following correctly fails
// assert_is_send(MyStruct.func(std::rc::Rc::new(4u64)));
}
但实际上,我不想让他们分开.我希望它们是一个功能,类似于async fn
如何自动完成它.一些类似的事情
use std::pin::Pin;
use std::future::Future;
struct MyStruct;
impl MyStruct {
fn func<T: 'static + ?Send>(&self, t: T) -> Pin<Box<dyn Future<Output = T> + ?Send>> {
Box::pin(async{t})
}
}
fn assert_is_send(_v: impl Send) {}
fn main() {
// This should
assert_is_send(MyStruct.func(4u64));
// And this should fail
assert_is_send(MyStruct.func(std::rc::Rc::new(4u64)));
}
像这样的事情在铁 rust 中可能发生吗?我可以手动编写异步特征魔法并修改它,而不是使用异步特征 crate ,如果这是一种让它工作的方法.
我有一些 idea ,但还没有真正落地:
- 使用最小专业化认证来专攻
Send
?但这一功能似乎不会很快稳定下来,所以可能不是最好的 Select . - 返回一个自定义的
MyFuture
类型,而不是只返回impl Future
和impl Send for MyFuture where T: Send
?不过,这可能很困难,因为我必须能够命名Future
和async
代码通常会生成impl Future
个无法命名的类型. - 编写一个过程性宏,如果它识别到输入类型为
Send
,则将返回类型加+ Send
.实际上,过程性宏能检测到某个类型是否实现了Send
吗?我猜这是不可能的,因为它们只在令牌流上工作.