Why does feature implementation for Box <T> conflict with Fn ()?
The simplest program that demonstrates this behavior:
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 ); } Fail compilation:
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 My questions:
- As far as I can tell
Box<T>does not implement theFn()trait. Then why does the above example not work? - What is the correct implementation for what I'm trying to do?
I just started to study Rust. Thank you for your help.
+7
Vikas
source share1 answer
Both are conflicting, because the Box<T> can have a T implementation of CanSpeak and Box<T> implementations of Fn() . The rules of rust coherence do not correspond to what is, but what can be.
Here is an example of an implementation of Fn() for Box<Cow> that would clearly explode if it allowed your two common attribute implementations:
// (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, _: ()) { } } +6
Chris morgan
source share