如果没有为 `&String` 实现 `Into<String>`,为什么这些实现会发生冲突?
If `Into<String>` is not implemented for `&String`, why are these implementations conflicting?
我问了一个 为什么 String
没有实现 From<&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
实现,所以它没有找到 Into<String>
为 [=19= 的实现].那么现在怎么会出现冲突呢?
此外,即使我打开 #![feature(specialization)]
,也检测到相同的冲突。
错误信息
根据这个问题的一个答案,错误消息似乎没有引导我到正确的轨道。
所以让我post责怪错误信息,因为它可能会在未来改变。
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`
对我来说,这是编译器声称存在真正的冲突,而不是潜在的冲突。
此代码适用于专业化
#![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
编辑
为什么上一个问题的代码无法编译?
因为当你在
中将 &s
传递给 new
let st: MyStruct = MyStruct::new(&s);
编译器将 &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
The compiler now claim that the two implementation 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 for &String
错误的发生只是因为编译器无法决定哪个实现更好specialized
,即使您使用专业化也是如此。
错误是由孤儿规则引起的(参见 The Book 第二版第 10.2 章 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);
}
我问了一个 String
没有实现 From<&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
实现,所以它没有找到 Into<String>
为 [=19= 的实现].那么现在怎么会出现冲突呢?
此外,即使我打开 #![feature(specialization)]
,也检测到相同的冲突。
错误信息
根据这个问题的一个答案,错误消息似乎没有引导我到正确的轨道。
所以让我post责怪错误信息,因为它可能会在未来改变。
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`
对我来说,这是编译器声称存在真正的冲突,而不是潜在的冲突。
此代码适用于专业化
#![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
编辑
为什么上一个问题的代码无法编译? 因为当你在
中将&s
传递给 new
let st: MyStruct = MyStruct::new(&s);
编译器将 &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
The compiler now claim that the two implementation 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 for &String
错误的发生只是因为编译器无法决定哪个实现更好specialized
,即使您使用专业化也是如此。
错误是由孤儿规则引起的(参见 The Book 第二版第 10.2 章 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);
}