rust 不匹配的类型^预期为`Result〈R,i32>`,发现`Result〈(Vec< i32>,u64),i32>`

w1jd8yoj  于 2023-03-23  发布在  其他
关注(0)|答案(1)|浏览(162)

我想写一个看领事服务的fn,但是我的代码报错了,怎么修复我的代码?怎么理解正确的方法?
tip:fn watch_service〈F,R〉(&self,callback:其中F:FnMut(Result〈R,i32〉)必须不改变。

error[E0308]: mismatched types
  --> src/test.rs:12:18
   |
10 |     fn watch_service<F, R>(&self, callback: F) where F: FnMut(Result<R, i32>) {
   |                         - this type parameter
11 |         let r = self.get_instances(13);
12 |         callback(r);
   |         -------- ^ expected `Result<R, i32>`, found `Result<(Vec<i32>, u64), i32>`
   |         |
   |         arguments to this function are incorrect
   |
   = note: expected enum `Result<R, _>`
              found enum `Result<(Vec<i32>, u64), _>`
note: callable defined here
  --> src/test.rs:10:57
   |
10 |     fn watch_service<F, R>(&self, callback: F) where F: FnMut(Result<R, i32>) {
   |                                                         ^^^^^^^^^^^^^^^^^^^^^

我的代码在这里:

use std::error::Error;

pub trait Watch {
    fn watch_service<F, R>(&self, _: F) where F: FnMut(Result<R, i32>) ;
}

pub struct Client {}

impl Watch for Client {
    fn watch_service<F, R>(&self, callback: F) where F: FnMut(Result<R, i32>) {
        let r = self.get_instances(13);
        callback(r);
    }
}

impl Client {
    fn get_instances(&self, ws : i32) -> Result<(Vec<i32>, u64), i32> {
        Ok((vec![1], 0))
    }
}

#[test]
fn watch_service_test() {
    let client = Client{};
    client.watch_service(|r| {
        match r {
            Ok((services, _)) => {
                assert_eq!(services, vec![1]);
            }
            Err(e) => {
                eprintln!("err: {}", e);
            }
        }
    });
}
euoag5mw

euoag5mw1#

你指定R作为一个不受限制的泛型,这意味着方法的调用者可以为它选择任何他们想要的类型(FileTcpStreamString&str,...)。编译器没有办法神奇地将所有可能的类型与你试图给予它的(Vec<i32>, u32)匹配,毕竟Rust是严格类型的。
由于您特别要求不更改watch_service的签名,因此唯一的解决方案是

  • 更改get_instances以返回某个泛型类型:
fn get_instances<R>(&self, ws: i32) -> Result<R, i32> {
        Err(0)
    }

当然,没有办法生成任意类型,所以我们可以返回的唯一值是所有的Err,其中包含任何有效的i32

  • 或者将返回的类型更改为Result<R, i32>,同样,我们无法创建R,因此我们只能给予Err
fn watch_service<F, R>(&self, callback: F) where F: FnMut(Result<R, i32>) {
        let r = self.get_instances(13).and_then(|_| Err(0));
        callback(r);
    }

这绝对不是你想要的,因为它非常无用。
你可能需要考虑改变watch_service的签名,毕竟,我能想到的最宽松的方法是将R限制为(Vec<i32>, u64)可以转换的类型:

fn watch_service<F, R>(&self, callback: F)
where
    R: TryFrom<(Vec<i32>, u64)>,
    F: FnMut(Result<R, i32>),
{
    let r = self
        .get_instances(13)
        .and_then(|v| R::try_from(v).map_err(|_| 0 /* any i32 */));
    callback(r);
}

另一种方法是直接要求回调来处理(Vec<i32>, u64)本身:

fn watch_service<F>(&self, callback: F) where F: FnMut(Result<(Vec<i32>, u64), i32>) {
    let r = self.get_instances(13);
    callback(r);
}

相关问题