我成功地让Rust类型检查器进入了一个无限循环。一个非常相似的程序可以顺利编译。为什么我想要的程序不能编译?
为了节省您的时间和精力,我制作了两个程序的最小版本,以便隔离问题。当然,这个最小版本是一个无意义的程序。您需要发挥想象力来看到我的动机。
成功
让我从正常工作的版本开始。结构体>包装了一个T。如果T可以被转换,类型Target可以从F转换而来。
当然,我最终想使用
这是我的实现:
为了节省您的时间和精力,我制作了两个程序的最小版本,以便隔离问题。当然,这个最小版本是一个无意义的程序。您需要发挥想象力来看到我的动机。
成功
让我从正常工作的版本开始。结构体>包装了一个T。如果T可以被转换,类型Target可以从F转换而来。
struct F<T>(T);
impl<T> From<F<T>> for Target where Target: From<T> {
fn from(a: F<T>) -> Target {
let b = Target::from(a.0);
f(&b)
}
}
这是一个调用示例:
fn main() {
let x = Target;
let y = F(F(F(x)));
let z = Target::from(y);
println!("{:?}", z);
}
这个运行并打印"Target"
。
失败
函数f
不会消耗其参数。我希望From
转换也不会消耗其参数,因为类型F<T>
可能很昂贵或无法克隆。我可以编写一个自定义特性FromRef
,它与std::convert::From
不同,它接受一个不可变借用而不是拥有的值:
trait FromRef<T> {
fn from_ref(a: &T) -> Self;
}
当然,我最终想使用
From<&'a T>
,但通过定义自己的trait,我可以更清楚地提出我的问题,而不会弄乱生命周期参数。(使用From<&'a T>
时,类型检查器的行为是相同的)。这是我的实现:
impl<T> FromRef<F<T>> for Target where Target: FromRef<T> {
fn from_ref(a: &F<T>) -> Target {
let b = Target::from_ref(&a.0);
f(&b)
}
}
这段代码可以编译通过,但是main()
函数无法正常运行:
fn main() {
let x = Target;
let y = F(F(F(x)));
let z = Target::from_ref(y);
println!("{:?}", z);
}
error[E0275]: overflow evaluating the requirement `_: std::marker::Sized`
--> <anon>:26:13
|
26 | let z = Target::from_ref(y);
| ^^^^^^^^^^^^^^^^
|
= note: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: required because of the requirements on the impl of `FromRef<F<_>>` for `Target`
= note: required because of the requirements on the impl of `FromRef<F<F<_>>>` for `Target`
= note: required because of the requirements on the impl of `FromRef<F<F<F<_>>>>` for `Target`
etc...
我做错了什么吗?
更新
我已经随机修复了它!
问题在于我忘记为Target实现FromRef<Target>。因此,我现在想知道编译器在想什么?我仍然无法将问题与错误消息联系起来。