Types 锈蚀:预期类型,发现不透明类型

Types 锈蚀:预期类型,发现不透明类型,types,rust,actix-web,Types,Rust,Actix Web,我想制作一个辅助函数,用于在actix中呈现模板,如下所示: fn呈现\u响应( tera:web::Data, 模板名称:&str, 上下文:&上下文, )->impl应答器{ 匹配tera.render(模板名称、上下文){ Ok(渲染)=>HttpResponse::Ok().body(渲染), Err()=>HttpResponse::InternalServerError().body(“未能解析模板”), } } 我在下面这样的视图中使用它: 异步fn注册(tera:web::Da

我想制作一个辅助函数,用于在actix中呈现模板,如下所示:

fn呈现\u响应(
tera:web::Data,
模板名称:&str,
上下文:&上下文,
)->impl应答器{
匹配tera.render(模板名称、上下文){
Ok(渲染)=>HttpResponse::Ok().body(渲染),
Err()=>HttpResponse::InternalServerError().body(“未能解析模板”),
}
}
我在下面这样的视图中使用它:

异步fn注册(tera:web::Data)->impl响应程序{
让mut data=Context::new();
数据。插入(“标题”、“注册”);
render_响应(tera,“signup.html”和数据)
}
如果视图与上面的视图一样简单,则一切正常,但如果视图稍微复杂一点,则会出现问题:

异步fn登录(tera:web::Data,id:Identity)->impl响应程序{
让mut data=Context::new();
数据。插入(“标题”、“登录”);
如果让一些(id)=id.identity(){
返回HttpResponse::Ok().body(格式!(“已登录:{}.”,id));
}
render_响应(tera,“login.html”和数据)
}
我得到的错误是:

错误[E0308]:类型不匹配
-->src\main.rs:101:5
|
42 |)->impl应答器{
|------找到的不透明类型
...
101 |呈现|响应(tera,“login.html”和数据)
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^预期结构为“actix_web::HttpResponse”,发现不透明类型
|
=注意:应为'actix_web::HttpResponse'类型`
找到不透明类型'impl actix_web::Responder`
我试图将
return-HttpResponse…
提取到一个单独的函数,该函数也返回
impl-Responder
,但现在出现了不同的错误:

错误[E0308]:类型不匹配
-->src\main.rs:101:5
|
42 |)->impl应答器{
|------找到的不透明类型
...
101 |呈现|响应(tera,“login.html”和数据)
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
=注意:应为'impl actix_web::Responder'(不透明类型at)
找到不透明类型'impl actix_web::Responder`(不透明类型位于)
=注:“impl Trait”的不同用法导致不同的不透明类型

我真的不明白为什么会发生这种情况以及如何修复它。

当函数返回类似于
impl Responder
的内容时,这意味着它返回实现
Responder
的某种类型。编译器可以推断出该类型,但它是“不透明的”对于任何调用方来说,这意味着您不能对类型实际是什么进行任何假设。即使编译器有更多的信息,类型也总是在函数边界处匹配。这一点很重要,这样人们就可以在函数级别对代码进行推理,而不必在继承人的头颅

函数也必须只返回一种类型,因此当编译器遇到这样的函数时:

async fn login(tera: web::Data<Tera>, id: Identity) -> impl Responder {
    let mut data = Context::new();
    data.insert("title", "Login");

    if let Some(id) = id.identity() {
        return HttpResponse::Ok().body(format!("Already logged in: {}.", id));
    }

    render_response(tera, "login.html", &data)
}

Returning
impl Responder
返回实现
Responder
特征的具体类型。您没有明确指定该类型,但它仍然是编译器推断的单一固定类型。
login()
函数返回两种可能不同的类型,一方面是不透明的
impl响应程序
,另一方面是
HttpResponse
。在这两种情况下,实际的具体类型都是
HttpResponse
,但是
render\u template()的原型
不能保证这一点。修复此具体示例的一个选项是制作
render\u template()
return
HttpResponse
取而代之。目前还不清楚该解决方案是否适用于您的所有用例。如果适用,请给出一些解决此问题的建议。另请参见。明白了,我认为这类似于其他语言的接口。任何实现给定特性的类型都可以。我理解我现在把它弄坏了。
fn render_response(
    tera: web::Data<Tera>,
    template_name: &str,
    context: &Context,
) -> HttpResponse;