我设法让Rust类型检查器进入无限循环。一个非常类似的程序编译没有麻烦。为什么我不想编译程序?
为了节省您的时间和精力,我已经制作了两个程序的最小版本来隔离问题。当然,最小版本是一个毫无意义的程序。你必须用你的想象力去看我的动力。
让我先介绍一下有效的版本。结构F<T>
包裹T
。 Target
类型可以从F<T>
提供的T
罐头转换。
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);
}
此runs并打印"Target"
。
函数f
不使用其参数。如果From
转换也没有使用它的参数,我会更喜欢它,因为类型F<T>
可能很昂贵或无法克隆。我可以通过接受不可变借用而不是拥有值来编写与std::convert::From
不同的自定义特征FromRef
:
trait FromRef<T> {
fn from_ref(a: &T) -> Self;
}
当然,我最终想要使用From<&'a T>
,但是通过定义我自己的特性,我可以更清楚地问我的问题,而不会弄乱生命周期参数。 (使用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...
我做错了什么?
问题是我忘了为FromRef<Target>
实施Target
。
所以我现在想知道:编译器在想什么?我仍然无法将问题与错误消息联系起来。
答案 0 :(得分:0)
您无法避免使用标准From
/ Into
特征中的输入。
它们被定义为始终使用输入。它们的定义将输入和输出都指定为拥有的类型,并且具有不相关的生存期,因此您甚至不能通过尝试使用引用来“作弊”。
如果要返回引用,则可以改为实现AsRef<T>
。或者,如果您的类型是精简包装程序/智能指针,则为Deref<T>
。您可以提供方法as_foo()
如果要返回一个新的(拥有的)对象,则约定是提供to_foo()
方法。