我一直在尝试impl Trait
,在构建递归函数时遇到了这个错误:
error[E0308]: if and else have incompatible types
--> src/main.rs:16:5
|
16 | / if logic {
17 | | one(false)
18 | | } else {
19 | | two()
20 | | }
| |_____^ expected opaque type, found a different opaque type
|
= note: expected type `impl Meow` (opaque type)
found type `impl Meow` (opaque type)
以下是要复制的代码(Rust playground link):
trait Meow {
fn meow();
}
struct Cat(u64);
impl Meow for Cat {
fn meow() {}
}
fn one(gate: bool) -> impl Meow {
if gate {
one(false)
} else {
two()
}
}
fn two() -> impl Meow {
Cat(42)
}
fn main() {
let _ = one(true);
}
我一直无法找到有关此特定问题的文档,但奇怪的是,编译器返回一个错误,该错误粗略地说“这两个相同的事物是不同的”。
请问有什么方法可以支持impl Trait
语法吗?
答案 0 :(得分:5)
免责声明:此答案假定读者理解-> impl Trait
需要返回单个类型;参见this question for returning different types。
Rust的核心原则之一是类型检查完全由功能,类型等的接口驱动,而实现则被忽略。
关于-> impl Trait
功能,这通过将每个-> impl Trait
视为不透明类型的语言来体现,仅由其来源的功能来识别。
因此,您可以调用同一函数两次:
use std::fmt::Debug;
fn cat(name: &str) -> impl Debug { format!("Meow {}", name) }
fn meow(g: bool) -> impl Debug {
if g {
cat("Mario")
} else {
cat("Luigi")
}
}
fn main() {
println!("{:?}", meow(true));
}
但是,即使在-> impl Trait
后面隐藏了至少一个函数,即使它们返回相同的类型,也无法调用它们:
use std::fmt::Debug;
fn mario() -> impl Debug { "Meow Mario" }
fn luigi() -> &'static str { "Meow Luigi" }
fn meow(g: bool) -> impl Debug {
if g {
mario()
} else {
luigi()
}
}
fn main() {
println!("{:?}", meow(true));
}
收益:
error[E0308]: if and else have incompatible types --> src/main.rs:8:9 | 8 | / if g { 9 | | mario() 10 | | } else { 11 | | luigi() 12 | | } | |_________^ expected opaque type, found &str | = note: expected type `impl std::fmt::Debug` found type `&str`
在-> impl Trait
后隐藏了两个:
use std::fmt::Debug;
fn mario() -> impl Debug { "Meow Mario" }
fn luigi() -> impl Debug { "Meow Luigi" }
fn meow(g: bool) -> impl Debug {
if g {
mario()
} else {
luigi()
}
}
fn main() {
println!("{:?}", meow(true));
}
产生与您相同的错误消息:
error[E0308]: if and else have incompatible types --> src/main.rs:8:5 | 8 | / if g { 9 | | mario() 10 | | } else { 11 | | luigi() 12 | | } | |_____^ expected opaque type, found a different opaque type | = note: expected type `impl std::fmt::Debug` (opaque type) found type `impl std::fmt::Debug` (opaque type)
没有。
该语言在这里没有特殊情况下的递归,因此没有意识到在所提出的问题中,只涉及一种类型。相反,它注意到fn one(...) -> impl Meow
和fn two(...) -> impl Meow
并得出结论,它们是不同的不透明类型,因此编译时统一是不可能的。
通过讨论递归的观点或讨论模块级可见性的观点,提交RFC来调整此方面可能是合理的。这超出了此答案的范围。
唯一的可能性是确保类型为 unique ,这需要命名。在名称中捕获了类型之后,就可以将其一致地应用到需要匹配的任何地方。
我会推荐您使用@Anders' answer来解决他的聪明方法。
答案 1 :(得分:4)
我认为理想的编译器会接受您的代码,但是当前的语言不允许进行递归推理,因此需要在这种情况下才能确定类型实际上是相同的。您可以通过使用类型变量抽象'wagtail.core.middleware.SiteMiddleware',
'wagtail.contrib.redirects.middleware.RedirectMiddleware',
类型来解决此丢失的功能:
impl Meow