为什么Rust函数的作用域比[duplicate]更一般

hrirmatl  于 2023-01-21  发布在  其他
关注(0)|答案(1)|浏览(103)
    • 此问题在此处已有答案**:

Calling a generic async function with a (mutably) borrowed argument(1个答案)
2天前关闭。
我试图将一个函数作为参数之一传递给另一个函数,但遇到了one type is more general than the other错误。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e4074efd53fdf9e43d8f209405745dc0

  1. use std::future::Future;
  2. async fn constraint<A, Fut, L>(args: A, lambda: L)
  3. where
  4. A: 'static + Send,
  5. Fut: Future<Output = ()> + 'static,
  6. L: Fn(&A) -> Fut + 'static,
  7. {
  8. lambda(&args).await;
  9. }
  10. fn main() {
  11. constraint("hello".to_string(), lambda);
  12. }
  13. async fn lambda(_: &String) -> () {}

下面是错误消息:

  1. error[E0308]: mismatched types
  2. --> src/main.rs:13:5
  3. |
  4. 13 | constraint("hello".to_string(), lambda);
  5. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
  6. |
  7. = note: expected trait `for<'a> <for<'a> fn(&'a String) -> impl Future<Output = ()> {lambda} as FnOnce<(&'a String,)>>`
  8. found trait `for<'a> <for<'a> fn(&'a String) -> impl Future<Output = ()> {lambda} as FnOnce<(&'a String,)>>`
  9. note: the lifetime requirement is introduced here
  10. --> src/main.rs:7:18
  11. |
  12. 7 | L: Fn(&A) -> Fut + 'static,
  13. | ^^^
  14. For more information about this error, try `rustc --explain E0308`.

我不想改变lambda函数,因为我想在while循环中,用输入流中的第二个参数,多次调用它,但是我可以改变约束函数。
到目前为止,我试着给约束函数添加一个生存期,但我不确定这是否正确,因为A上应该已经有一个静态生存期:

  1. async fn constraint<'a, A, Fut, L>(args: A, lambda: L)
  2. where
  3. A: 'static + Send,
  4. Fut: Future<Output = ()> + 'static,
  5. L: Fn(&'a A) -> Fut + 'static,
  6. {
  7. lambda(&args).await;
  8. }

对应错误:

  1. |
  2. 3 | async fn constraint<'a, A, Fut, L>(args: A, lambda: L)
  3. | -- lifetime `'a` defined here
  4. ...
  5. 9 | lambda(&args).await;
  6. | -------^^^^^-
  7. | | |
  8. | | borrowed value does not live long enough
  9. | argument requires that `args` is borrowed for `'a`
  10. 10 | }
  11. | - `args` dropped here while still borrowed

还尝试移动参数,但得到相同的错误:

  1. use std::future::Future;
  2. async fn constraint<A, Fut, L>(args: A, lambda: L)
  3. where
  4. A: 'static + Send,
  5. Fut: Future<Output = ()> + 'static,
  6. L: Fn(&A) -> Fut + 'static,
  7. {
  8. async move {
  9. lambda(&args).await;
  10. };
  11. }
  12. fn main() {
  13. constraint("hello".to_string(), lambda);
  14. }
  15. async fn lambda(_: &String) -> () {}
mm5n2pyu

mm5n2pyu1#

这是因为lambdaimpl Future返回类型隐式地捕获了它的参数的生存期,但是constraint要求它是'staticFut: Future<Output = ()> + 'static
你的lambda可以反糖为如下形式:

  1. fn lambda<'a>(_: &'a String) -> impl Future<Output = ()> + 'a {
  2. async {}
  3. }

它的输出有一个生存期绑定到它的输入参数。
虽然constraint期望签名看起来像这样:

  1. fn lambda<'a>(_: &'a String) -> impl Future<Output = ()> + 'static {
  2. async {}
  3. }

您可以只使用最后一个定义(不需要显式生存期'a)。
我不确定是否以及如何使用async来表达这个意思

展开查看全部

相关问题