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

Reply via email to