FromStr和TryFrom<String>特质有什么区别?

8
当我在Rust中使用Serde库时,我尝试为一个实现了FromStr的类型添加一个#[serde(try_from = String)]容器属性,以便从字符串中解析。不幸的是,这对于Serde来说似乎还不够,从编译器错误消息中可以明显看出,我还必须手动实现TryFrom<String>

为什么不会自动为所有实现FromStr的类型实现TryFrom<String>?为什么会有一个单独的trait用于从字符串进行可失败转换?这两个trait之间有什么区别?

1
我认为答案是“出于历史原因的平均值”:据我所知,FromStr要早得多,而TryFrom则是后来才添加的。然而,你期望的特质自动实现听起来很合理,也许有技术上的原因,不能轻易地实现它。 - Zólyomi István
2
你可能会发现 serde_with 很有用,它允许你使用 FromStrDisplay 自动(反)序列化,并且还有许多其他方便的功能。 - trent
感谢提供 serde_with 的链接。我会看一下,但由于我的项目是针对 WASM 的,所以我对额外的依赖非常敏感,以免增加输出文件大小。 - blerontin
2个回答

11
FromStr在Rust 1.0中就已经稳定了,TryFrom在Rust 1.34中得到了稳定; 在其存在之前使用该特征将非常困难。
为什么不为所有实现FromStr的类型自动实现TryFrom<String>呢?
这将导致与已经实现了TryFromFromStr的类型产生歧义。需要一种高级的特化形式才能允许这样做。
为什么有一个单独的trait用于从字符串进行容错转换? FromStr从一个借用的字符串片段(&str)创建一个拥有值,因此它在语义上不同于获取一个String的所有权。 TryFrom<String>将允许您重用为String分配的内存。
更接近的类比是impl<'a> TryFrom<&'a str> for ...,但是在特质中使用lifetime会在从字符串解析值的“简单”情况下使其更加复杂。
另请参见:
- Should Rust implementations of From/TryFrom target references or values? - How is there a conflicting implementation of `From` when using a generic type? - What is the difference between TryFrom<&[T]> and TryFrom<Vec<T>>? - How do I implement FromStr with a concrete lifetime? - What are reasons for FromStr trait not exposing lifetime? - How do I write the lifetimes for references in a type constraint when one of them is a local reference?

1
我应该注意到这两个特征具有不同的生命周期要求。实现TryFrom<&str>并使用#[serde(try_from = "&str")]似乎可以正常工作。 - blerontin

1

TryFrom是一种通用的特质,可为“任何”类型实现。根据文档:

简单且安全的类型转换,可能在某些情况下以受控的方式失败。

Type -> Type

它还提供了TryInto的自动实现。

FromStr主要用于解析类型,同样如文档所述:

FromStr的from_str方法通常会隐式地通过str的parse方法使用。

str -> Type

实现它以便被str::parse使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接