【发布时间】:2019-05-30 16:06:42
【问题描述】:
我一直在尝试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 语法同时进行这种回避吗?
【问题讨论】:
-
这是一个稍微不同的问题。这里编译器可以理想地推断
one返回的impl Meow必须与two返回的impl Meow相同,无论它是什么,在这种情况下,两个if分支将统一。它只是没有,今天。 -
@AndersKaseorg 虽然问题可能不同,但答案仍然与副本中的相同
-
@你好我不同意。一开始我也是这么想的,后来仔细看了这个问题,想出了my answer,这个递归模式特有的,不需要trait对象。
-
我同意@AndersKaseorg,虽然链接答案中的解决方法也解决了这个问题,但失败的原因有些不同:在链接答案中有两种不同的类型都实现了这个特征;然而,在这个问题中,只有一种类型实现了该特征,更聪明的编译器可以接受它。
-
@MatthieuM.:嗯,是的,如果调用者和被调用者是不同的函数,那就是真的。但是递归函数呢,它在检查递归调用时可以使用自己的实现吗?也许有理论上的理由不这样做,但我没有看到任何实际的缺点。
标签: rust