How would I specify that 'self' must implement some traits?

I made a custom trait, where Reverse (which is also a custom trait) and multiply have to be implemented for vec_obj.

This calculates the magintude squared of a vector.

trait SquareMag2 {
    fn size<T: Reverse + Mul>(vec_obj: T) -> f32;
}

This is not quite what I want.
What I really would like to do is something like this:

trait SquareMag2 {
    fn size<T: Reverse + Mul>(self: T) -> f32;
}

However this doesn't work. Does anyone know how to specify trait constraints on self?

If I try to do this it complains about that self must be Self or something that dereferences to it.
The help says to consider changing self to: &self, &mut self, self: Box<Self> and other similar nonsense that I don't quite understand how that would help my situation.

where Self: Reverse + Mul should work on the method itself, or you can simply add a trait SquareMag2: Reverse + Mul supertrait bound if it always needs to hold.

(Note that your self: T declaration wouldn't make any sense for any other purpose either, because self is always the receiver type. It simply can't be "generic" like that – to a trait, an implementor is always a single type.)

4 Likes

Thanks so much for this. I was not aware you could put constraints directly onto types. I will keep that in mind for the future, although, I don't think my regular use of generics is bad. This was probably some kind of edge case. Thank you.

While you did solve my issue, this has a side effect that the size of self must be known at compile time. Hopefully this won't become an issue later. Just wanted to mention it though.

You can’t pass the unsized type to the function size anyways.

1 Like

I'm not sure where else you think you can put constraints. Generic trait bounds establish relationships between types and traits.

1 Like

Because 99.5% of trait bounds are of the form T: Trait1 + Trait2, it's probably not uncommon for a Rust learner to develop a mental model in which trait bounds can only constrain type parameters, and that is indeed how bounds work in languages like Java. It can be a real moment of enlightenment to realize that Rust allows trait bounds like where i32: From<T> and not just where T: Into<i32>, and that because of this where clauses are strictly more powerful than the <T: Trait> short notation.

6 Likes

I don't think that's what OP had in mind? Self is also a type variable, and it's the one being constrained here. So that's not the typevar vs. concrete type distinction.

That's why my question was: where else did OP come across trait bounds? Trait bounds always go on a type (be it a variable or a known one), so I didn't get what else OP was getting to.

1 Like

At least this is how I interpret it.

1 Like

Yes, this is what I mean I guess I didn't know the rust lingo to say that though thanks.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.