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

Reply via email to