Generics 为什么对Box<;T>;与Fn()冲突?
演示此行为的简化程序:Generics 为什么对Box<;T>;与Fn()冲突?,generics,rust,traits,Generics,Rust,Traits,演示此行为的简化程序: use std::boxed::Box; struct Cow; trait CanSpeak { fn speak(&self); } impl CanSpeak for Cow { fn speak(&self) { println!("moo"); } } impl<F: Fn()> CanSpeak for F { fn speak(&self) { sel
use std::boxed::Box;
struct Cow;
trait CanSpeak {
fn speak(&self);
}
impl CanSpeak for Cow {
fn speak(&self) {
println!("moo");
}
}
impl<F: Fn()> CanSpeak for F {
fn speak(&self) {
self();
}
}
impl<T: CanSpeak> CanSpeak for Box<T> {
fn speak(&self) {
(**self).speak()
}
}
fn lol_speak() {
println!("lol")
}
fn lets_speak<T: CanSpeak>(t: & T) {
t.speak();
}
fn main() {
let cow = Cow;
lets_speak( &cow );
lets_speak( &lol_speak );
let boxed_cow = Box::new(Cow);
lets_speak( &boxed_cow );
}
使用std::boxed::Box;
结构牛;
我会说话{
fn说话(和自我);
}
我能为母牛说话吗{
fn讲话(自我){
println!(“moo”);
}
}
impl可以代表F{
fn讲话(自我){
self();
}
}
impl可以为Box说话{
fn讲话(自我){
(**self.speak()
}
}
fn lol_speak(){
println!(“lol”)
}
fn让你说话(t:&t){
t、 说();
}
fn main(){
让牛=牛;
让我们说话(牛);
让你说话(&lol\u说话);
让装箱的牛=箱子::新的(牛);
让我们说话(和装箱的牛);
}
编译失败,原因是:
test.rs:15:1: 19:2 error: conflicting implementations for trait `CanSpeak` [E0119]
test.rs:15 impl<F: Fn()> CanSpeak for F {
test.rs:16 fn speak(&self) {
test.rs:17 self();
test.rs:18 }
test.rs:19 }
test.rs:15:1: 19:2 help: run `rustc --explain E0119` to see a detailed explanation
test.rs:21:1: 25:2 note: note conflicting implementation here
test.rs:21 impl<T: CanSpeak> CanSpeak for Box<T> {
test.rs:22 fn speak(&self) {
test.rs:23 (**self).speak()
test.rs:24 }
test.rs:25 }
error: aborting due to previous error
test.rs:15:1:19:2错误:trait`CanSpeak`[E0119]的实现冲突
测试:15个impl可以代表F{
测试。rs:16 fn口语(和自我){
测试rs:17个self();
test.rs:18}
test.rs:19}
test.rs:15:1:19:2帮助:运行'rustc--explain E0119'查看详细说明
test.rs:21:1:25:2注意:注意这里的实现冲突
测试。rs:21 impl可以为Box说话{
测试。rs:22 fn口语(和自我){
test.rs:23(**self).speak()
test.rs:24}
test.rs:25}
错误:由于上一个错误而中止
我的问题是:
Box
未实现Fn()
trait。那么为什么上面的例子失败了呢我刚开始学生锈。感谢您的帮助。这两种方法确实存在冲突,因为类型
Box
可能有T
实现CanSpeak
和Box
实现Fn()
。规则不是关于什么是,而是关于什么可以是
下面是一个为Box
实现Fn()
的示例,如果它允许两个通用的trait实现,那么显然会发生爆炸:
// (This attribute on the crate.)
#![feature(unboxed_closures, core)]
impl Fn<()> for Box<Cow> {
extern "rust-call" fn call(&self, _: ()) { }
}
impl FnMut<()> for Box<Cow> {
extern "rust-call" fn call_mut(&mut self, _: ()) { }
}
impl FnOnce<()> for Box<Cow> {
type Output = ();
extern "rust-call" fn call_once(self, _: ()) { }
}
//(板条箱上的此属性。)
#![特征(未固定的_闭合,核心)]
适用于盒子的impl Fn{
外部“锈调用”fn调用(&self,:()){}
}
框的impl FnMut{
外部“锈调用”fn调用{mut(&mut self,{}
}
一次装盒{
类型输出=();
外部“锈调用”fn调用一次(self,\()){
}
谢谢克里斯的回复,但恐怕我还是没有收到。你能解释一下在这种情况下,Box
有什么特别之处,Rust认为它会发生冲突吗?例如,如果我正确理解您的解释,任何容器,比如说Arc
也应该冲突,因为T
可以实现CanSpeak
,而Arc
可以实现Fn()
。但是在我的示例中,用Arc
替换Box
效果很好,没有什么特别之处。只是您为一个可能重叠的特性提供了两个通用实现。那么为什么Arc
可以工作呢?在我的示例中,如果我用Arc
替换Box
,它编译时没有任何错误。Box是特殊的,它被标记为#[基本]
(而Arc不是)。确切的规则是什么,我现在还不知道。哦,不,下一个难题是:Fn
特征也被标记为#[基本]
,它也很特别!正确的灌木丛!使用不同的边界,它将发生冲突。