Rust 为什么添加第二个impl会阻止对参数进行deref强制?

Rust 为什么添加第二个impl会阻止对参数进行deref强制?,rust,language-lawyer,Rust,Language Lawyer,我在尝试将impladdforstring添加到标准库时遇到了这个问题。但是我们可以很容易地复制它,而不需要操作员的诡计。我们从这一点开始: trait MyAdd{ fn添加(自身,rhs:rhs)->自身; } 字符串的impl MyAdd{ fn添加(mut self,rhs:&str)->self{ 自推式街(rhs); 自己 } } 很简单。使用此选项,将编译以下代码: a=String::from(“a”); 设b=String::from(“b”); 我的添加::添加(a和b);

我在尝试将impl
addforstring
添加到标准库时遇到了这个问题。但是我们可以很容易地复制它,而不需要操作员的诡计。我们从这一点开始:

trait MyAdd{
fn添加(自身,rhs:rhs)->自身;
}
字符串的impl MyAdd{
fn添加(mut self,rhs:&str)->self{
自推式街(rhs);
自己
}
}
很简单。使用此选项,将编译以下代码:

a=String::from(“a”);
设b=String::from(“b”);
我的添加::添加(a和b);
请注意,在本例中,第二个参数表达式(
&b
)的类型为
&String
。然后将其强制解除为
&str
,函数调用开始工作

但是,让我们尝试添加以下impl:

impl MyAdd for String{
fn添加(多个自身,rhs:char)->自身{
自推式(rhs);
自己
}
}
()

现在,上面的
MyAdd::add(a,&b)
表达式导致以下错误:

error[E0277]:特性绑定'std::string::string:MyAdd'不满足
-->src/main.rs:24:5
|
2 | fn添加(自我,rhs:rhs)->自我;
|--------------------------------------MyAdd::add所需`
...
24 | MyAdd::add(a和b);
|^^^^^^^^^^^未为'std::string::string'实现特性'MyAdd'`
|
=帮助:找到了以下实现:

这是为什么?对我来说,似乎只有在只有一个候选函数的情况下才进行解除强制。但这在我看来是错误的。为什么规则会是这样?我试图查看规范,但在参数deref强制方面没有发现任何内容。

正如您自己所解释的,编译器专门处理只有一个有效的
impl
的情况,并且可以使用它来驱动类型推断:

其中指出,如果只找到一个impl,编译器会“急切地确认”它,这就允许发生deref强制(以及其他事情)。对于多个impl候选对象,这种情况不会发生

第二部分是,deref强制只会发生在预期类型已知的站点,而不是推测性地发生。参见参考资料中的。Impl选择和类型推断必须首先显式地找到
MyAdd::add(&str)
,以尝试将参数强制为
&str

如果在这种情况下需要解决方法,请使用类似于
&*b
&b[…]
b的表达式作为第二个参数。

这让我想起(我写的)。编译器一般知道该特性,当只有一个
impl
适用时,它可以通过选择该
impl
中使用的类型参数来消除歧义。在另一个问答中,我使用这种能力让编译器(看起来)在调用站点选择一个
impl
,这是它通常无法做到的。大概在这种情况下,这就是允许它进行解除强制的原因。但这只是猜测。其中指出,如果只找到一个impl,编译器会“急切地确认”它,这就允许发生deref强制(以及其他事情)。对于多个impl候选对象,这种情况不会发生。所以我想这就是答案,但我还是想知道更多。在rustc的书中可能会有所帮助,但据我所知,它并没有具体说明这一点。