Why Rust could not accept (public) fields or methods as trait restrictions

suppose we have:

pub struct Student{pub name:String, pub score:i32}
pub struct Teacher{pub name:String, pub school:i32}
pub struct School{pub name:String, pub students:Vec<Student>}

and we want to wrote a DisplayName trait for all of them.

we could easily wrote macros, but without macros, (IMHO,) we must repeat this almost same code for 3 times

impl DisplayName for Student {
    fn display(&self){println!("{}",self.name)}
}

why couldn't we wrote something like:

impl<T> DisplayName for T where T.name:String { // please do not discuss about my awful syntax used here, syntax related issues could be discussed later.
    fn display(&self){println!("{}",self.name)}
}

Same things happened to methods. we already defined lots of Add method for primitive types, but we must use num_trait otherwise those Add function could not be used to declare a new trait.

What prevent Rust from making it possible?

T.name:String

Does T need to be a local type? Does the name field need to be public? If no for 1 and yes for 2, does that mean that exposing a previously private field changes the set of traits implemented by the type?

Add can be used to implement another trait:

use std::ops::Add;

trait Double {
    fn double(a: Self) -> Self;
}

impl<T> Double for T
where
    T: Add<Self, Output = Self> + Copy,
{
    fn double(a: Self) -> Self {
        a + a
    }
}

Very rarely is something impossible. The default state for all features is that Rust don't have them, because someone has to make a case for them before they can become a thing.

But for this specific case, Rust probably wouldn't do it that way because that's duck typing, which Rust doesn't really do outside macros.

It's possible that one day Rust will have something related, though, perhaps like

4 Likes

Very very early versions of Rust actually had structural typing which would make this possible, but it has been changed to nominal typing.

It would be interesting to see what would happen if Rust introduced structurally typed interfaces. Much of the current type system has structural features already (auto-traits, variance, and derives), so this wouldn't be unprecedented.