Inconvenience of using functions defined in traits, an ugly workaround, and proposed solution

In my opinion, there is a clear and long recognized need to solve this general problem. I've been wanting this feature, but I had thought of it differently. I wanted to have a notion of inherent traits. The idea was roughly that you could add "supertraits" to structs or enums:

pub trait Methods { ... }

struct Struct: Methods {
    f: u32
}

As a result of doing so, two things are true:

(1) We must be able to prove that every Struct instance has a Methods impl

(2) You can use the methods from the Methods trait as if they were inherent to struct.

My idea does not allow you to add "inherent methods" to Struct from outside the defining crate, however, whereas your proposed syntax might. This is also something I would very much like, though I had thought of it as an orthogonal problem. I am not keen on defining throw-away traits for that purpose, which is of course what you have to do now. I have previously proposed the idea of 'crate-local' inherent impls, but that had the downside that it could only work for inherent impls, not trait impls ("crate-local impls of traits" might be nice but have much broader complications) -- and, actually, inherent impls would maybe have some of the same complications if we applied specialization to them.

On a related note, I would eventually like the idea to put inherent methods right into the struct declaration. I'm not sure what purpose is served by forcing people to pull them out into a distinct impl block (mind you, I like the ability to put impl blocks in other places and add methods from all over, I just wouldn't mind a shorthand for the most common case):

struct Foo<T: Ord, U> {
    fields...;

    fn bar(&self) { ... }
}

It's a bit awkward, because fields are comma-separated, though no more so than the proposed field-in-trait-syntax (really have to get back to that RFC...), not entirely by coincidence. You could imagine extending this notion to impls of traits, which might then also make the trait impl inherent. In this case, condition (1) above doesn't apply, because we're providing the impl right there. The downside of course is the rightward drift.

struct Foo<T: Ord, U> {

    impl Eq {
        fn bar(&self) { .. }
    }
}
2 Likes