我发现,当泛型关系错综复杂时,仅通过阅读简单的源代码是无法追踪的.

有没有办法透露编译器对特定泛型 struct 或函数的实例化轨迹?

Elaborated:

感谢你对这个问题感兴趣.它在这里进行了详细阐述.我最近在研究经度 crate .因此,以它为例.

use warp::Filter;

async fn handler_without_parameter() -> Result<impl warp::Reply, warp::Rejection> {
    Ok(warp::reply::json(&"dumb".to_string()))
}

fn main() {
    let get_items = warp::get()
        .and(warp::path("/"))
        .and(warp::path::end())
        .and_then(handler_without_parameter); //Ok here
}
async fn handler_without_parameter() -> Result<impl warp::Reply, warp::Rejection> {
    Ok(warp::reply::json(&"dumb".to_string()))
}

fn main() {
    let para: HashMap<String, String> = HashMap::new();
    let para_filter = warp::any().map(move || para.clone()); // A filter with data

    let get_items = warp::get()
        .and(warp::path("/"))
        .and(warp::path::end())
        .and(para_filter)      //chain with the data filter
        .and_then(handler_without_parameter); // error[E0593]: function is expected to take 1 argument, but it takes 0 arguments
}

在链接筛选器(它与数据一起)之后,方法and_then的参数预期为1个自变量.我对and_then的这个需求变化很好奇,所以我试着弄清楚这个方法的单形化过程.

https://docs.rs/warp/0.3.5/warp/trait.Filter.html#method.and_then

    fn and<F>(self, other: F) -> And<Self, F>
    where
        Self: Sized,
        <Self::Extract as Tuple>::HList: Combine<<F::Extract as Tuple>::HList>,
        F: Filter + Clone,
        F::Error: CombineRejection<Self::Error>,
    {
        And {
            first: self,
            second: other,
        }
    }


    fn and_then<F>(self, fun: F) -> AndThen<Self, F>
    where
        Self: Sized,
        F: Func<Self::Extract> + Clone,
        F::Output: TryFuture + Send,
        <F::Output as TryFuture>::Error: CombineRejection<Self::Error>,
    {
        AndThen {
            filter: self,
            callback: fun,
        }
    }


基本特征是:

pub trait FilterBase {
    type Extract: Tuple; // + Send;
    type Error: IsReject;
    type Future: Future<Output = Result<Self::Extract, Self::Error>> + Send;

    fn filter(&self, internal: Internal) -> Self::Future;

    fn map_err<F, E>(self, _internal: Internal, fun: F) -> MapErr<Self, F>
    ...
}

我不明白为什么添加的链接会引起and_then方法的需求更改,因为对我来说,这里的泛型关系非常复杂.

Even with the hints provided by rust-analyzer, it doesn't help a lot, because the Extract = ... part is eclipsed. enter image description here

推荐答案

问题是para_filter返回一些东西,而下一个函数必须接受前一个函数返回的东西.因此,如果para_filter返回HashMap<String, String>,则handler_without_parameter必须将HashMap<String, String>作为其唯一参数.如果para_filter不返回任何内容,则handler_without_parameter将不得不将空元组作为其唯一参数(handler_without_parameter(_: ()) -> ...).

我是如何解决这个问题的:相当不透明的错误消息

error[E0593]: function is expected to take 1 argument, but it takes 0 arguments
  --> src/main.rs:16:10
   |
4  | async fn handler_without_parameter() -> Result<impl warp::Reply, warp::Rejection> {
   | --------------------------------------------------------------------------------- takes 0 arguments
...
16 |         .and_then(handler_without_parameter); // error[E0593]: function is expected to take 1 argument, but it takes 0 arguments
   |          ^^^^^^^^ expected function that takes 1 argument
   |
   = note: required for `fn() -> impl Future<Output = Result<impl Reply, Rejection>> {handler_without_parameter}` to implement `warp::generic::Func<(HashMap<String, String>,)>`

关键是截图中的最后一行,note: required for ... {handler_without_parameter} to implement warp::generic::Func<(HashMap<String, String>,)>--如果有疑问,最好总是阅读完整的编译器诊断.如果您使用的是 rust 蚀分析器,那么您可以将鼠标悬停在错误上,然后单击"显示完整的编译器诊断".

另外,这与单形化无关,而是与其输入类型和输出类型共享泛型参数和/或泛型约束的泛型函数有关.参数为and会影响其输出的类型,进而影响调用and_then的对象的类型,进而影响and_then预期的参数类型.

Rust相关问答推荐

有条件默认实现

go 掉包装 struct 中的泛型

当第二个`let`依赖于第一个`let()`时,如何在一行中有多个`let()`?

将PathBuf转换为字符串

将serde_json读入`VEC<;T&>;`( rust 色)时出现问题

如何实现Serde::Ser::Error的调试

为什么&;mut buf[0..buf.len()]会触发一个可变/不可变的borrow 错误?

如何在Rust中缩短数组

如何重命名 clap_derive 中的子命令占位符?

具有多个键的 HashMap

为什么编译器看不到这个 `From` impl?

tokio::sync::broadcast::Receiver 不是克隆

当推送到 HashMap 中的 Vector 时,类型 `()` 无法取消引用

为什么 &i32 可以与 Rust 中的 &&i32 进行比较?

改变不实现克隆的 dioxus UseState struct

在 RefCell 上borrow

在 Rust 中返回对枚举变体的引用是个好主意吗?

如何在 nom 中构建负前瞻解析器?

返回引用的返回函数

如何从 Rust 应用程序连接到 Docker 容器中的 SurrealDB?