1
votes

I'm reading the book Programming Rust, and learned about Rust's traits and generic types. And I find that type bounds can be placed on the methods of a trait. Then I constructed the following trait and implemented it for a struct.

use std::fmt::Display;
trait Test<T> {
    fn show(&self)
    where
        T: Display;
    fn test(&self);
}

struct S<T> {
    field: T,
}

impl<T> Test<T> for S<T> {
    fn show(&self)
    where
        T: Display,
    {
        println!("My field: {}", self.field);
    }

    fn test(&self) {
        println!("Just for test");
    }
}

The follwing code would not compile just as expected:

struct R;

fn main() {
    let s = S { field: R {} };
    s.show();
}

But the following code would compile and run.

struct R;

fn main() {
    let s = S { field: R {} };
    s.test();
}

Shouldn't Rust just reject the code when s is defined as S { field: R{} }? Does it mean that s is an instance of S that implements trait T partially?

1
Please use rustfmt to format your code. You can find it under tools in the upper right corner on the playground.hellow

1 Answers

0
votes

Can Rust traits be partially implemented?

No. Either all in, or nothing.

But why is one code compiling but the other won't.

The reason is the extra bound on show

fn show(&self) where T: Display;

This means, that when you want to call this method, your T must implement Display. If it's not implemented, you can't call it.

Rusts "generics" work different than C++ for example.

In C++ you have SFINAE (Substitution failure is not an error). This is kind of duck typing.
Rust works on bounds, that means you have to specify what kind of traits a your "generic" must impelement to use the functions. In this case you can call Display::fmt because you specified, that your T must implement that trait.

This bound is not specified for your test method and therefore you can call it with whatever type you want.