Consider this program: """ trait AdderIncr { fn add(&self, x: Self) -> Self; fn incr(&mut self); }
impl AdderIncr for int { fn add(&self, x: int) -> int { *self + x } fn incr(&mut self) { *self += 1; } } fn incrAdd(x: &mut AdderIncr, y: &mut AdderIncr) { x.incr(); x.add(y); } fn main() {} """ It fails to compile: """ Documents/test.rs:13:1: 13:10 error: cannot call a method whose type contains a self-type through an object Documents/test.rs:13 x.add(y); ^~~~~~~~~ """ The Self type is meaningless in object methods, since I have no way to ensure that y has the same underlying type as x. Thus, only a subset of the methods of a trait are available on the corresponding object, which means that objects can't automatically implement their corresponding trait. That means any impls that implement a trait for all types that implement AdderIncr, for example, won't implement that trait for &AdderIncr, since &AdderIncr doesn't implement AdderIncr. On Sat, Oct 19, 2013 at 2:47 AM, Oren Ben-Kiki <o...@ben-kiki.org> wrote: > Hmmm.... That sounds strange. Shouldn't `obj: &T` allow me to invoke > `obj.method_of_T()`? > > For example, how did I manage to invoke the `data.print(...)` method via > the borrowed `data: &PrintWithSpice` pointer? Automatic dereference? And if > so, why didn't it work for `Writer` as well? > > On Sat, Oct 19, 2013 at 9:29 AM, Steven Fackler <sfack...@gmail.com>wrote: > >> If T is a trait, its trait objects ~T, @T and &T do not implement T. >> There is an implementation of Writer for @Writer, but not for ~Writer or >> &Writer which is why you're seeing that error. >> >> Steven Fackler >> >> >> On Fri, Oct 18, 2013 at 11:27 PM, Oren Ben-Kiki <o...@ben-kiki.org>wrote: >> >>> Ugh, I was too optimistic. Yes, I can write my code using `MyWriter`, >>> but I can't cast any @Writer (such as `io::stdout()`) to it. I guess I >>> should just use `@Writer` everywhere for now :-( >>> >>> This raises the question of how come the compiler is smart enough to >>> figure out a `@Writer` has the trait `WriterUtil`, but isn't smart enough >>> to figure out a `&Writer` has the trait... >>> >>> >>> On Sat, Oct 19, 2013 at 9:08 AM, Oren Ben-Kiki <o...@ben-kiki.org>wrote: >>> >>>> I run into the following problem (the code below is a toy example). >>>> >>>> ``` >>>> use std::io::Writer; // Makes no difference if added/removed. >>>> >>>> trait PrintWithSpice { >>>> fn print(&self, writer: &Writer, spice: bool); >>>> } >>>> >>>> struct Bar { >>>> bar: ~PrintWithSpice, >>>> } >>>> >>>> impl Bar { >>>> pub fn print(&self, writer: &Writer) { >>>> self.bar.print(writer, false); >>>> Bar::print_via_borrowed(writer, &self.bar); >>>> } >>>> >>>> fn print_via_borrowed(writer: &Writer, data: &PrintWithSpice) { >>>> // Invoking the `print` function via the borrowed pointer to >>>> the `PrintWithSpice` trait: >>>> // Works fine, as expected.. >>>> data.print(writer, true); >>>> } >>>> } >>>> >>>> struct Foo { >>>> foo: bool >>>> } >>>> >>>> impl PrintWithSpice for Foo { >>>> fn print(&self, writer: &Writer, spice: bool) { >>>> // Invoking the `write_str` function via the borrowed pointer >>>> to the `Writer` trait: >>>> // error: failed to find an implementation of trait >>>> std::io::Writer for &std::io::Writer<no-bounds> >>>> // What is going on? >>>> writer.write_str(format!("foo: {:b} spice: {:b}", self.foo, >>>> spice)); >>>> } >>>> } >>>> ``` >>>> >>>> I didn't understand what the compiler is complaining about. "failed to >>>> find an implementation of Foo for &Foo<no-bounds>"? A Foo is a Foo, no? >>>> Calling a function via a borrowed pointer to a trait should just work (it >>>> does a few lines above). >>>> >>>> After digging I discovered what the compiler really meant (I think). >>>> The `write_str` method is defined for `WriterUtils` rather than for >>>> `Writer`. So, if I replace `Writer` by `WriterUtil` in the above code, it >>>> compiles fine. >>>> >>>> So, I ended up defining `trait MyWriter: Writer + WriterUtil` and I am >>>> using that instead of `Writer` all over my code. I can see doing that as a >>>> workaround, but it doesn't smell right to me. >>>> >>>> So: >>>> >>>> * Why is the compiler complaining about not finding an implementation >>>> for `Writer` when the method I invoke is from `WriterUtil`? >>>> >>>> * Since there is an `impl<T: Writer> for WriterUtil`, shouldn't the >>>> compiler be "sufficiently smart" to deduce that the code is valid in the >>>> 1st place? >>>> >>>> * Until the compiler is "sufficiently smart" (or, if there is a good >>>> reason why it would never be), shouldn't we rename `Writer` to >>>> `BasicWriter` and define `trait Writer: BasicWriter, WriterUtil {}` so >>>> `&Writer` would become more usable? >>>> >>> >>> >>> _______________________________________________ >>> Rust-dev mailing list >>> Rust-dev@mozilla.org >>> https://mail.mozilla.org/listinfo/rust-dev >>> >>> >> > > _______________________________________________ > Rust-dev mailing list > Rust-dev@mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > >
_______________________________________________ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev