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

Reply via email to