If you always want Page to use Name::name, you could make Page a subtrait of Name:
trait Page: Name {
fn show(&self);
}
I looked this up and it looks like the opposite of this. In Rust you'd call UFCS "method call syntax" and Name::name might be called "associated function syntax".
Yeah, that might not be the right term.I might've confused it with something else. Anyway, here's the docs for the syntax: Call expressions - The Rust Reference
My goal is to reduce a boilerplate code. Currently I use macros containing that code. I thought of riding of macros and incorporate that code in other treat implementation and do just composition of two treats implementation when a boilerplate code absorber trait takes the job. I appreciate if you illustrate a super trait approach of doing that.
I see the problem as name should appear in both traits. Actually Page refers it in some its implementations as an abstract method. Now : I introduced a treat as Name, and I want to provide a concrete implementation of name in the treat. So I do not need to provide name in all separate treat implementations. I do not see how I can do that, it's why I asked for more elaborated example.
If you use supertraits you only need to provide the name implementation once (in Name), and users only need to bound on Page to use name. What else do you want?
You wrote Name: Page. This declares that any type implementing Name must implement Page, but it says nothing about some T: Page.
The answer discussed above by drewtato used Page: Name. This says that any T: Page must also implement Name, meaning that those types will have .name() accessible.
trait Name {
fn name(&self) -> String;
}
// vvvv
trait Page: Name {
// .name() will also be callable because
// Name is a supertrait
fn show(&self);
}
fn foo<P: Page>(page: &P) {
let name = page.name();
println!("{name}");
page.show();
}
I do not see much difference from your code which is perfectly compilable.
Errors
error[E0407]: method `main_load` is not a member of trait `Name`
--> test.rs:22:5
|
22 |
/ fn main_load(&self) -> Result<String, String> {
23 | | Ok(self.name())
24
| | }
| |_____^ not a member of trait `Name`
error[E0277]: the trait bound `RealPage: Page` is not satisfied
--> test.rs:21:15
|
21 |
impl Name for RealPage {
| ^^^^^^^^ the trait `Page` is not implemented for `RealPage`
|
help: this trait has no implementations, consider adding one
--> test.rs:5:1
|
5 | trai
t Page {
| ^^^^^^^^^^
note: required by a bound in `Name`
--> test.rs:15:13
|
15 | trait Name: Page {
| ^^^^ required by this bound in `Name`
error[E0277]: the trait bound `RealPage: Page` is not satisfied
--> test.rs:23:17
|
23 |
Ok(self.name())
| ^^^^ the trait `Page` is not implemented for `RealPage`
|
help: this trait has no implementations, consider adding one
--> test.rs:5:1
|
5 | trai
t Page {
| ^^^^^^^^^^
note: required by a bound in `Name::name`
--> test.rs:15:13
|
15 | trait Name: Page {
| ^^^^ required by this bound in `Name::name`
16 | fn name(&self) -> String {
| ---- required by a bound in this associated function
error[E0599]: no method named `main_load` found for struct `RealPage` in the current scope
--> test.rs:28:41
|
1
| struct RealPage {
| --------------- method `main_load` not found for this struct
...
28
| println!{"NamePage: {}", RealPage{}.main_load().unwrap()}
| ^^^^^^^^^ m
ethod not found in `RealPage`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `Page` defines an item `main_load`, perhaps you need to implement it
--> test.rs:5:1
|
5 |
trait Page {
| ^^^^^^^^^^
You can't override a super-trait method in a sub-trait. Implementations in traits are defaults that can be overridden when a type is implemented for that trait.
Each sub and super-trait must be implemented separately, for each type. You can't implement a super-trait method when implementing the sub-trait.
So you probably can't do exactly what you wanted. But here is a playground that compiles that you can try modifying.