简体   繁体   English

Rust:理解特征“From”的实现

[英]Rust: Understanding trait `From` implementation

How to understand trait FromWhatever in rust如何理解 rust 中的 trait FromWhatever

The Rust book explains following: Rust 书中解释如下:

The From trait allows for a type to define how to create itself from another type, hence providing a very simple mechanism for converting between several types. From trait 允许一个类型定义如何从另一个类型创建自己,因此提供了一个非常简单的机制来在多个类型之间进行转换。

Sounds simple enough.听起来很简单。 Lets try as simple example as possible:让我们尝试尽可能简单的例子:

use std::str::FromStr;

struct MyStructure {}

// auto accepted suggestion from language server.
impl FromStr for MyStructure {
    type Err = (); // I've added this

    fn from_str(_s: &str) -> Result<Self, Self::Err> {
        Ok(Self {}) // I've added this
    }
}

fn main() {
    const INPUT: &str = "test";
    let _tmp: MyStructure = MyStructure::from(INPUT);
}

playground 操场

Compiling test_range_2 v0.1.0 (/home/pavel/Repositories/test_range_2)
error[E0308]: mismatched types
   --> src/main.rs:15:47
    |
15  |     let _tmp: MyStructure = MyStructure::from(INPUT);
    |                             ----------------- ^^^^^ expected struct `MyStructure`, found `&str`
    |                             |
    |                             arguments to this function are incorrect
    |
note: associated function defined here
   --> /home/pavel/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/convert/mod.rs:374:8
    |
374 |     fn from(_: T) -> Self;
    |        ^^^^

For more information about this error, try `rustc --explain E0308`.
error: could not compile `test_range_2` due to previous error

So I expected this behavior:所以我期待这种行为:

let target: TARGET_TYPE = TARGET_TYPE::from::<SOURCE_TYPE>(input_var: SOURCE_TYPE);

Compared to the example in the rust book :rust 书中的示例相比:

let num = Number::from(30);

It seems to me like a reasonable assumption.在我看来,这是一个合理的假设。

However, reading the error message: "expected struct MyStructure , found &str ".但是,阅读错误消息:“expected struct MyStructure , found &str ”。 Does that mean that syntax is like this?这是否意味着语法是这样的?

let target: TARGET_TYPE = TARGET_TYPE::from::<TARGET_TYPE>(input_var: TARGET_TYPE);

If, that's true, then code in the rust book should also fail with the error "expected Number , found i32 ", but it doesn't.如果,那是真的,那么 rust 书中的代码也应该失败并出现错误“expected Number ,found i32 ”,但事实并非如此。

I expected my solution to work because I've implemented the trait FromStr , and I'm trying to create object from &str (see the "from" and "str"?).我希望我的解决方案能够工作,因为我已经实现了trait FromStr ,并且我正在尝试从&str创建 object (请参阅“from”和“str”?)。 Which is also the type that was autocompleted by language server after I've typed impl FromStr for MyStructure .这也是在我impl FromStr for MyStructure后由语言服务器自动完成的类型。 What am I missing?我错过了什么? I want to impl FromStr for all my types but that compiler is not making it easy.我想为我的所有类型实现 FromStr,但编译器并不容易。

Solution解决方案

use std::str::FromStr;

struct MyStructure {}

impl FromStr for MyStructure {
    type Err = ();

    fn from_str(_s: &str) -> Result<Self, Self::Err> {
        Ok(Self {})
    }
}
impl From<&str> for MyStructure {
    fn from(_: &str) -> Self {
        Self {}
    }
}

fn main() {
    const INPUT: &str = "test";
    let _tmp0 = MyStructure::from_str(INPUT);
    let _tmp1 = MyStructure::from(INPUT);
}

I implemented trait FromStr but was referring to trait From<&str> .我实现了trait FromStr但指的是trait From<&str> Since there is a trait in standard lib that looks like this:由于标准库中有一个如下所示的特征:

trait From<T> -> T

compiler tried to use that in stead.编译器试图改用它。

From and FromStr are completely different and entirely unrelated traits. FromFromStr是完全不同且完全不相关的特征。

The first one performs 1 -> 1 infaillible conversions, while the latter is used to parse strings (it's a pretty old trait, its modern equivalent is TryFrom but because FromStr hooks into str::parse() it remains convenient and popular).第一个执行 1 -> 1 可靠的转换,而后者用于解析字符串(这是一个相当古老的特性,它的现代等价物是TryFrom但因为FromStr挂钩到str::parse()它仍然方便和流行)。

Here you impl FromStr , which does nothing for your From::from call.在这里你实现FromStr ,它对你的From::from调用没有任何作用。

Instead you get told about a blanket implementation: converting a type to itself is a no-op, so the standard library has相反,您会被告知一揽子实现:将类型转换为自身是空操作,因此标准库具有

impl<T> From<T> for T

which just returns itself.它只是返回自己。

Hence the compiler's error message: when it encounters因此编译器的错误信息:当它遇到

MyStructure::from(INPUT);

and tries to resolve this to an implementation, the only impl From<?> for MyStructure it finds is the blanket implementation,并尝试将其解决为一个实现,它找到的唯一impl From<?> for MyStructure是一揽子实现,

impl From<MyStructure> for MyStructure

and thus it tells you that it expects an argument of type MyStructure (the only possible input for the implementations it found), but found an &str (what you actually gave it).因此它告诉您它需要一个MyStructure类型的参数(它找到的实现的唯一可能输入),但找到了一个&str (您实际给它的)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM