我问了一个相关的问题,为什么没有执行From<&String>for String.我现在想要创建自己的特征,如下所示:
#[derive(Debug)]
struct MyStruct(String);
impl MyStruct {
fn new<T>(t: T) -> MyStruct
where
T: MyIntoString,
{
MyStruct(t.my_into())
}
}
trait MyIntoString {
fn my_into(self) -> String;
}
impl<'a> MyIntoString for &'a String {
fn my_into(self) -> String {
self.clone()
}
}
impl<I> MyIntoString for I
where
I: Into<String>,
{
fn my_into(self) -> String {
self.into()
}
}
fn main() {
let s: String = "Hello world!".into();
let st: MyStruct = MyStruct::new(&s);
println!("{:?}", st);
}
Run Code Online (Sandbox Code Playgroud)
编译器现在声称两个实现MyIntoString是冲突的.这对我来说更加怪异,因为我们已经在另一个From<&String>没有实现的问题中看到了String,所以它没有找到Into<String>for 的实现&String.那么现在为何如此矛盾呢?
此外,即使我打开#![feature(specialization)],也检测到相同的冲突.
错误消息
根据这个问题的一个答案,看起来错误信息并没有引导我走上正轨.
因此,让我发布错误消息,因为它可能会在未来发生变化.
error[E0119]: conflicting implementations of trait `MyIntoString` for type `&std::string::String`:
--> src/main.rs:23:1
|
17 | / impl<'a> MyIntoString for &'a String {
18 | | fn my_into(self) -> String {
19 | | self.clone()
20 | | }
21 | | }
| |_- first implementation here
22 |
23 | / impl<I> MyIntoString for I
24 | | where
25 | | I: Into<String>,
26 | | {
... |
29 | | }
30 | | }
| |_^ conflicting implementation for `&std::string::String`
Run Code Online (Sandbox Code Playgroud)
对我来说,这是编译器声称存在真正的冲突,而不是潜在冲突.
该错误是由孤儿规则引起的(请参阅本书第二版第 10.2 章,位于“在类型上实现特征”末尾)。
当您使用的 crate发生微小更改(根据RFC#1105 )时,这些可以防止您的代码被破坏。如果标准库的作者决定实现Into<String>for &String,那么您的程序将包含冲突的 for 定义my_into,并且会中断。添加特征实现应该是一个小的改变,并且不应该破坏你的程序。
这篇文章为该规则提供了理由。
本书建议使用新类型模式来解决这个问题。
#[derive(Debug)]
struct MyStruct(String);
impl MyStruct {
fn new<T>(t: T) -> MyStruct
where
T: Into<String>,
{
MyStruct(t.into())
}
}
struct Wrapper<'a>(&'a String);
impl<'a> From<Wrapper<'a>> for String {
fn from(t: Wrapper<'a>) -> String {
t.0.clone()
}
}
fn main() {
let s: String = "Hello world!".into();
let st: MyStruct = MyStruct::new(Wrapper(&s));
println!("{:?}", st);
}
Run Code Online (Sandbox Code Playgroud)