Rust:预期类型,发现不透明类型
Rust: expected type, found opaque type
我想在actix中做一个渲染模板的辅助函数,如下所示:
fn render_response(
tera: web::Data<Tera>,
template_name: &str,
context: &Context,
) -> impl Responder {
match tera.render(template_name, context) {
Ok(rendered) => HttpResponse::Ok().body(rendered),
Err(_) => HttpResponse::InternalServerError().body("Failed to resolve the template."),
}
}
我在下面这样的视图中使用它:
async fn signup(tera: web::Data<Tera>) -> impl Responder {
let mut data = Context::new();
data.insert("title", "Sign Up");
render_response(tera, "signup.html", &data)
}
如果视图像上面那样简单,一切正常,但是如果视图稍微复杂一点,我就会遇到问题:
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)
}
我得到的错误:
error[E0308]: mismatched types
--> src\main.rs:101:5
|
42 | ) -> impl Responder {
| -------------- the found opaque type
...
101 | render_response(tera, "login.html", &data)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `actix_web::HttpResponse`, found opaque type
|
= note: expected type `actix_web::HttpResponse`
found opaque type `impl actix_web::Responder`
我试图将 return HttpResponse...
提取到一个单独的函数中,该函数也 returns impl Responder
,但我现在遇到了不同的错误:
error[E0308]: mismatched types
--> src\main.rs:101:5
|
42 | ) -> impl Responder {
| -------------- the found opaque type
...
101 | render_response(tera, "login.html", &data)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
|
= note: expected type `impl actix_web::Responder` (opaque type at <src\main.rs:104:28>)
found opaque type `impl actix_web::Responder` (opaque type at <src\main.rs:42:6>)
= note: distinct uses of `impl Trait` result in different opaque types
我不太明白为什么会发生这种情况以及如何解决它。
当一个函数 return 类似于 impl Responder
时,这意味着它 return 是 某些 类型实现 Responder
.编译器可以推断出类型,但它对任何调用者来说都是“不透明的”,这意味着您不能对实际类型做出任何假设。即使编译器有更多的信息,类型总是在函数边界匹配。这很重要,这样人们就可以在函数级别推理代码,而不必在头脑中保留有关程序各行的所有信息。
一个函数也只能return一种类型,所以当编译器遇到这样的函数时:
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)
}
它看到最后的陈述 return 是一个不透明的 impl Responder
和早期的 return
陈述 return 是一个具体的 HttpResponse
。即使您知道它们实际上是同一类型,那只是因为您碰巧知道 render_response
是如何实现的。这很好,因为它可以防止更改代码的不相关部分破坏此功能:您不希望更改 render_response
的 body 导致 类型 login
不匹配。
将render_response
的return类型改为具体类型即可:
fn render_response(
tera: web::Data<Tera>,
template_name: &str,
context: &Context,
) -> HttpResponse;
我想在actix中做一个渲染模板的辅助函数,如下所示:
fn render_response(
tera: web::Data<Tera>,
template_name: &str,
context: &Context,
) -> impl Responder {
match tera.render(template_name, context) {
Ok(rendered) => HttpResponse::Ok().body(rendered),
Err(_) => HttpResponse::InternalServerError().body("Failed to resolve the template."),
}
}
我在下面这样的视图中使用它:
async fn signup(tera: web::Data<Tera>) -> impl Responder {
let mut data = Context::new();
data.insert("title", "Sign Up");
render_response(tera, "signup.html", &data)
}
如果视图像上面那样简单,一切正常,但是如果视图稍微复杂一点,我就会遇到问题:
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)
}
我得到的错误:
error[E0308]: mismatched types
--> src\main.rs:101:5
|
42 | ) -> impl Responder {
| -------------- the found opaque type
...
101 | render_response(tera, "login.html", &data)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `actix_web::HttpResponse`, found opaque type
|
= note: expected type `actix_web::HttpResponse`
found opaque type `impl actix_web::Responder`
我试图将 return HttpResponse...
提取到一个单独的函数中,该函数也 returns impl Responder
,但我现在遇到了不同的错误:
error[E0308]: mismatched types
--> src\main.rs:101:5
|
42 | ) -> impl Responder {
| -------------- the found opaque type
...
101 | render_response(tera, "login.html", &data)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
|
= note: expected type `impl actix_web::Responder` (opaque type at <src\main.rs:104:28>)
found opaque type `impl actix_web::Responder` (opaque type at <src\main.rs:42:6>)
= note: distinct uses of `impl Trait` result in different opaque types
我不太明白为什么会发生这种情况以及如何解决它。
当一个函数 return 类似于 impl Responder
时,这意味着它 return 是 某些 类型实现 Responder
.编译器可以推断出类型,但它对任何调用者来说都是“不透明的”,这意味着您不能对实际类型做出任何假设。即使编译器有更多的信息,类型总是在函数边界匹配。这很重要,这样人们就可以在函数级别推理代码,而不必在头脑中保留有关程序各行的所有信息。
一个函数也只能return一种类型,所以当编译器遇到这样的函数时:
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)
}
它看到最后的陈述 return 是一个不透明的 impl Responder
和早期的 return
陈述 return 是一个具体的 HttpResponse
。即使您知道它们实际上是同一类型,那只是因为您碰巧知道 render_response
是如何实现的。这很好,因为它可以防止更改代码的不相关部分破坏此功能:您不希望更改 render_response
的 body 导致 类型 login
不匹配。
将render_response
的return类型改为具体类型即可:
fn render_response(
tera: web::Data<Tera>,
template_name: &str,
context: &Context,
) -> HttpResponse;