2017-07-16 48 views
5

我問了relevant question爲什麼沒有執行From<&String>String。我現在想創建自己的特點如下所示:如果`Into <String>`沒有爲`&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); 
} 

編譯器現在聲稱的MyIntoString兩個實現是相互矛盾的。這對我來說更是如此,因爲我們已經在另一個問題中看到From<&String>沒有爲String實施,所以它沒有找到的執行&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` 

對我來說,這是編譯器聲稱存在真正的衝突,而不是潛在的衝突。

+0

相關:https://stackoverflow.com/questions/45033704/why-do-i-get-conflicting-implementations-of-trait-for-f32-which-does-not簡單 – Boiethios

回答

3

錯誤是由孤兒規則引起的(請參閱本書第二版10.230末尾的Implementing a trait on a type)。

這些可防止在您使用的箱子中發生細微變化時(如RFC#1105),破壞您的代碼。如果標準庫的作者決定爲&String執行Into<String>,那麼您的程序將包含衝突定義my_into,並且會中斷。性狀實施的增加應該是一個小改動,不應該破壞你的計劃。

This post提供了該規則的理由。

該書建議使用newtype pattern來解決此問題。

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

Playground link

+1

這段代碼與我的做法完全相同,但方式完全不同。這段代碼在'Wrapper <'a> ==&'a String'上實現'Into ',但是我的代碼在'&'String'上實現了'MyIntoString'。兩者都應該通過孤兒規則。 –

+2

號將'MyIntoString'(也就是'impl > MyIntoString for I')與'impl MyIntoString for'字符串'結合使用,可能會導致標準庫中的細微變化導致代碼破壞。 Newtype變體不會中斷。 – red75prime

+2

我沒有看到孤兒規則是如何相關的,因爲OP正在實現他自己的特徵'MyIntoString'。 – interjay

0

該代碼可以使用專業化

#![feature(specialization)] 

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

default impl<I> MyIntoString for I 
{ 
    default fn my_into(self) -> String { 
     String::from("FOO") 
    } 
} 

fn main() { 
    let s: String = "Hello world!".into(); 
    let st: MyStruct = MyStruct::new(&s); 
    println!("{:?}", st); 
} 

所以,AFAIU,你的版本不能專門因爲編譯器不能決定哪個版本更specialized

編輯

爲什麼從代碼以前的問題不能編譯? 因爲當你在

let st: MyStruct = MyStruct::new(&s); 

編譯器傳遞&snew考慮&s&String,並從std代碼時看到:

impl<T, U> Into<U> for T where U: From<T> 

impl<T, U> Into<U> for T where U: From<T> { 
    fn into(self) -> U { 
     U::from(self) 
    } 
} 

// From (and thus Into) is reflexive 
#[stable(feature = "rust1", since = "1.0.0")] 
impl<T> From<T> for T { 
    fn from(t: T) -> T { t } 
} 

而且由於From<&String>不是爲String它顯示編譯錯誤執行。所以,你必須明確地說,&s是從String可以構造類型,即&str

let st: MyStruct = MyStruct::new(&s as &str); 

,現在編譯器可以看到現在聲稱這

impl<'a> From<&'a str> for String 

編譯器,這兩個實施MyIntoString>衝突。這是更加古怪的我就像我們在其他>問題已經看到,從< &字符串>沒有實現絃樂,所以它 沒有找到進入的實施&字符串

錯誤僅僅因爲編譯器不能決定哪個實現更具有優勢,即使你使用專門化也是如此。

+0

這個問題的要點不在於專業化。這是關於爲什麼'&'一個字符串'被認爲是在這個上下文中執行'Into '而不是另一個。 –

+0

因爲自動解引用 –

+0

請在您的答案中解釋以及您的解決方法。 –

相關問題