Can we use `impl Trait` and `impl Trait for Trait`?


#1

It seems that Rust has supported the syntax impl Trait and impl Trait for Trait (see https://doc.rust-lang.org/nightly/src/core/any.rs.html#108-198 as an example). I would like to know whether this feature is stable or not and how to use it. What is the difference with impl Trait for Type?

Here is a simple testing example :

trait T {
    fn log(&self) -> String;
}

impl T {
   fn log(&self) -> String { "Trait T".to_string() }
}

struct S;

impl T for S {
    fn log(&self) -> String { "Struct S".to_string() }
}

enum E {
    A,
    B,
}

impl T for E {
    fn log(&self) -> String {
        match *self {
            E::A => "Enum E with variant A".to_string(),
            E::B => "Enum E with variant B".to_string(),
        } 
    }
}

fn main() {
    let s = S;
    let a = E::A;
    let b = E::B;
    println!("{}", s.log());
    println!("{}", a.log());
    println!("{}", b.log());
}

You can run it at http://is.gd/IOU2W5. How can we use the method log() of the implementation of trait T?


#2

Trait identifiers are slightly overloaded: they’ve got their normal thing (impl Trait for ..., T: Trait etc.), but they are also the name of the trait object type that allows for erasing a type and performing virtual dispatch of the trait’s method. So, these uses are just impl Type/impl Trait for Type using the trait name to refer to that trait object type, rather than the trait itself. E.g.

trait Trait {}
impl Trait {
    fn method(&self) {}
}

creates a inherent method called method on the trait object type Trait, with signature fn(&Trait).

In your example, T's log inherent method can (almost) be called by explicitly creating a Trait trait object. However, the fact that log is a method in the trait, and also an inherent method on the trait object type causes confusion, and, may in fact leave the inherent log method uncallable. Conventional uses of this sort of trick will not repeat method names. In any case, doing an explicit cast indicates that the inherent log method is being picked up as a method that could be called:

println!("{}", (&s as &T).log());

This fails with error:

<anon>:38:31: 38:36 error: multiple applicable items in scope [E0034]
<anon>:38     println!("{}", (&s as &T).log());
                                        ^~~~~
...
<anon>:38:31: 38:36 help: see the detailed explanation for E0034
<anon>:7:4: 7:53 note: candidate #1 is defined in an impl for the type `T + 'static`
<anon>:7    fn log(&self) -> String { "Trait T".to_string() }
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<anon>:3:5: 3:29 note: candidate #2 is defined in the trait `T`
<anon>:3     fn log(&self) -> String;
             ^~~~~~~~~~~~~~~~~~~~~~~~

Confusion about impls without for
#3

[quote=“huon, post:2, topic:3335”]
However, the fact that log is a method in the trait, and also an inherent method on the trait object type causes confusion, and, may in fact leave the inherent log method uncallable.
[/quote]I’d expect the inherent method to mask the trait method but

    let bb: Box<T> = Box::new(b);
    println!("{}", bb.log());

causes a multiple applicable items in scope error instead: http://is.gd/DlGjpL.