0

In rust I can put trait bounds on a template argument to guarantee it conforms to the functionality I want:

fn print<T:Debug>(t: T) {
    println!("{:?}", t);
}

Can I do something similar with fields?

fn print_name<T:HasNameField>(t: T) {
    println!("{:?}", t.name);
}

I'm not trying access a specific field (for which I could make some accessor trait). I am trying to promise a 3P function that I have certain fields, similar to how we promise functionality in a template w/Trait bounds.

My use case is that in yew I would like to create a form. Instead of just using <input type="text".../> I would like users to be able to create their own input fields and be able to build CustomForm. And then I could have:

#[function_component(CustomForm)]
fn custom_form<T: yew::Component>() -> Html {
    <form>
        <T name="field name"/>
    </form>
}

Currently this fails with the following message:

error[E0609]: no field `name` on type `<T as yew::Component>::Properties`
matanmarkind
  • 219
  • 3
  • 13

1 Answers1

3

As of Rust 1.62.0 (2022-06-30), traits cannot require fields. Though, you can use a function instead.

trait Named {
    fn get_name(&self) -> &str;
}

Then, just implement it as you would any other trait.

struct NameImpl;

impl Named for NameImpl {
    fn get_name(&self) -> &str {
        "my field name"
    }
}

You can use it as a type bound, and call get_name() as you please.

fn do_stuff_with_named<N: Named>(n: N) {
    println!("{}", n.get_name())
}
ImajinDevon
  • 287
  • 1
  • 11
  • 1
    Though in a situation like this, if you are writing the trait as well, you may simply want `do_stuff_with_named` to be _in_ the `Named` trait. – Chris Jun 22 '22 at 15:52
  • Unfortunately I don't have control over the call site. I am using the `yew` library. Otherwise I would have done the solution pointed to here. I think I really need a way for the call site to know that `name` is a field of T. – matanmarkind Jun 22 '22 at 17:08