如果没有为 `&String` 实现 `Into<String>`,为什么这些实现会发生冲突? [英] If `Into<String>` is not implemented for `&String`, why are these implementations conflicting?

查看:26
本文介绍了如果没有为 `&String` 实现 `Into<String>`,为什么这些实现会发生冲突?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我问了一个 相关问题,关于为什么没有实现 String 来自<&String>.我现在想创建我自己的特征如下:

I asked a relevant question about why there is no implementation of From<&String> for String. I now want to create my own trait as the following:

#[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);
}

编译器现在声称 MyIntoString 的两个实现是冲突的.这对我来说更奇怪,因为我们已经在另一个问题中看到 From<&String> 没有为 String 实现,所以它没有找到实现Into for &String.那么现在这怎么会发生冲突呢?

The compiler now claims that the two implementations of MyIntoString are conflicting. This is even weirder to me as we already see in the other question that From<&String> didn't implement for String and so it didn't find an implementation of Into<String> for &String. So how come this is conflicting now?

此外,即使当我打开 #![feature(specialization)] 时,也检测到相同的冲突.

Furthermore, even when I turned on #![feature(specialization)], the same conflict was detected.

错误信息

根据这个问题的一个答案,错误消息似乎没有引导我走上正轨.

According to one answer of this question, it looks like the error message didn't guide me to the right track.

所以让我把错误信息贴出来,因为它将来可能会改变.

So let me post the error message to blame, as it may changed in the future.

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`

对我来说,这是编译器声称存在真正的冲突,而不是潜在的冲突.

To me, this is a claim by the compiler that there is a REAL conflict, not a potential one.

推荐答案

该错误是由孤儿规则引起的(参见 The Book 第二版. Chapter 10.2 在 在类型上实现特征).

The error is caused by the orphan rules (see The Book second ed. chapter 10.2 at the end of Implementing a trait on a type).

这些可以防止您的代码在发生微小更改时中断(根据 RFC#1105) 在您使用的板条箱中.如果标准库的作者决定为 &String 实现 Into,那么您的程序将包含一个与 my_into 冲突的定义并会打破.添加 trait 实现应该是一个小改动,不应该破坏你的程序.

These prevents your code from breaking when there are minor changes (as per RFC#1105) in crates you use. If the authors of the standard library decided to implement Into<String> for &String, then your program would contain a conflicting definition for my_into and would break. The addition of a trait implementation should be a minor change and shouldn't break your program.

这篇文章 为该规则提供了理由.

This post provides justification for the rule.

本书建议使用 newtype 模式来解决这个问题.

The Book suggests using the newtype pattern to work around this issue.

#[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);
}

游乐场链接

这篇关于如果没有为 `&amp;String` 实现 `Into&lt;String&gt;`,为什么这些实现会发生冲突?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆