如果我为引用类型实现"TryFrom",为什么Rust中不会发生自动借用



假设我想在引用上实现转换。在这种情况下,它是从&f64 -> Foo转换而来的。

use std::convert::{TryFrom, TryInto};
struct Foo {
a: f64
}
impl TryFrom<&f64> for Foo {
type Error = String;
fn try_from(value: &f64) -> Result<Foo, String> {
Ok(Foo {
a: *value
})
}
}
fn main(){
let foo: Foo = 5.0.try_into().unwrap();
let bar: Foo = (&5.0).try_into().unwrap();
}

(是的,当然这是一个毫无意义和愚蠢的例子,但它有助于简化问题(

现在,主方法中的第二行,通过手动借用,成功了。然而,主方法中的第一行,在没有手动借用的情况下,由于以下错误而失败:

error[E0277]: the trait bound `Foo: From<{float}>` is not satisfied
--> src/main.rs:18:24
|
18 |     let foo: Foo = 5.0.try_into().unwrap();
|                        ^^^^^^^^ the trait `From<{float}>` is not implemented for `Foo`
|
= note: required because of the requirements on the impl of `Into<Foo>` for `{float}`
note: required because of the requirements on the impl of `TryFrom<{float}>` for `Foo`
--> src/main.rs:7:6
|
7  | impl TryFrom<&f64> for Foo {
|      ^^^^^^^^^^^^^     ^^^
= note: required because of the requirements on the impl of `TryInto<Foo>` for `{float}`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error

游乐场

为什么自动借款在这里不起作用?

正如错误消息所示,问题是the trait bound Foo: From<{float}> is not satisfied。当匹配特征时,Rust不会执行任何强制,而是探测合适的方法。这实际上记录在Rustonomicon中,读取

请注意,在匹配特征时,我们不执行强制(接收器除外,请参阅下一页(。如果某个类型U有一个impl,而T强制为U,则不构成T.的实现

下一页显示

假设我们有一个函数foo,它有一个接收器(self、&self或&mut-self参数(。如果我们调用value.foo((,编译器需要确定Self是什么类型,然后才能调用函数的正确实现。。。如果它不能调用这个函数(例如,如果函数的类型错误,或者没有为Self实现特性(,那么编译器会尝试添加一个自动引用。这意味着编译器尝试<amp;T>:foo(值(和<amp;mut T>:foo(值(。这被称为";autoref";方法调用。

因此,当匹配特征绑定时,Rust编译器将尝试仅对类型进行自动引用/取消引用。此外,rust中的点运算符只是完全限定函数调用的语法糖。因此,5.0.try_into().unwrap();将变为f64::try_into(5.0).unwrap();,并且由于TryInto没有为f64实现,因此Rust将尝试通过调用&f64::try_into(5.0).unwrap();来自动引用它。现在编译器可以找到为&f64实现的TryInto版本,但参数类型仍然不匹配:&f64try_into需要&f64作为参数类型,而当前调用提供f64,Rust编译器在检查特征绑定时不能对参数进行任何强制。因此,特征绑定仍然不匹配(&f64不能接受f64参数(,并且检查失败。因此,您将看到错误消息。

最新更新