An Exercise To Understand Rusts Trait Bounds Syntax
It’s time to start using these angled brackets I’ve been seeing a bit more. No more putting it off.
Let’s start easy
Let’s create a function that can receive any type which has implemented a trait, and call a method that is available from that trait.
When I see those angled brackets my brain goes a bit haywire, so I’m going to break it down a bit. Step by step let’s see what we are telling the compiler.
pub fn set_generic_age<T: AgeHandler>(entity: &mut T, new_age: u8) {…
Declare the function as a public function
Set the functions Name
Now I’m already lost because I understand that we’re telling the function that it’s going to need to ‘deal with a trait called AgeHandler’ But what does that mean?
The book and the Rust reference don’t explicitly say what happens with the compiler.
But they do make it clear that by implementing the trait bound, the compiler will associate the Generic Type you’ve passed in as though it should have that trait implemented already. NOTE: Regardless of what you name “T” in these generics, it will treat it as anything. I gave mine the exact name of an existing struct and it will still accept any struct that has the bound trait(s) implemented.
I’ve already covered handling this sort of thing so more details are available there.
Speaking of bounding trait(s)
It’s mostly the same as above. Once the method above makes sense, this part becomes pretty clear:
pub fn get_intro_string<T: NameHandler + AgeHandler>(entity: &T) -> String {…
The biggest difference is now there is a + in the trait bounding brackets. So the function scope is being setup to deal with Parameter (T) that should have both the NameHandler and the AgeHandler traits implemented. Nice.
I see lots of value in this
Especially when it comes to working with the compiler instead of against it. But only time will tell. Until then, let’s check out the last bit I want to cover in this post.
Using a Where clause for type bounds
This was pretty cool too. I can specify more advanced requirements for scenarios where more or different traits are required for one of a set of parameters. Let’s look at the code:
Right in the declaration of the function, there is a where clause, and it’s referencing the trait bounds declared within the <>, and applying the traits that should be applied to those specific parameters.
This is cool! At first glance, I find the syntax a bit off-putting. But on the other hand, I’d much rather this than this crazy list of + symbols one after the other with a comma hidden somewhere in between the params.
Conclusion
Trait bounds for functions using the angled brackets apply a trait or multiple traits to one of the parameters in the function definition. What a mouthful.
This is a way to tell the compiler to expect the utilization of specific implemented traits in the scope of that function and to enforce that parameters coming into that function do already have those traits implemented.