Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I have to 'use' a trait in order to call methods defined in that trait?

Tags:

rust

I'm toying with the cgmath library. I have the following main.rs file:

extern crate cgmath;

use cgmath::vector::{Vector3, EuclideanVector};

fn main() {
    let mypoint = Vector3 { x: 1f64, y: 1f64, z: 3f64 };

    println!("The length of the vector is {}, and the length squared is {}", mypoint.length(), mypoint.length2());
}

In my use line, when I omit EuclideanVector, I am given the following compilation error:

type 'cgmath::vector::Vector3<f64>' does not implement any method in scope named 'length'

It appears that the Rust compiler cannot find the length() method unless I import one of the traits that Vector3 uses. Delving into the source code, it looks like the length method is defined within the EuclideanVector trait.

Intuitively, I should not need to import an trait to use a type that inherits said trait. Is there a technique to do so that I am missing? Is this a nuance specific to the cgmath library? Is this an idiomatic part of Rust that I should become accustomed to?

like image 618
Elliott Avatar asked Dec 20 '22 12:12

Elliott


1 Answers

You're thinking of traits in terms of inheritance. It might make more sense if you think of a trait as a module that's overloadable with respect to the Self type. From this perspective, it makes sense that the trait has to be in scope in order for the compiler to know about its methods, just as a module has to be in scope in order to use it. A particular implication of this is that implementations can be declared alongside the trait they implement rather than the type they implement it for. In this situation, clearly if your code doesn't know about the trait, it can't use its methods.

Another motivation for the current behaviour is that multiple traits can define methods with the same name, and when you have such a conflict for traits implemented for the same type, you can no longer use method call syntax to access their methods. Instead, you have to use function call syntax in order to specify which trait the method is a member of (the trait acting as the module the method is in). If method call syntax used all traits in your program rather than just the ones in scope for method resolution, you'd end up with these conflicts much more often, since you'd have name conflicts with methods in traits that your code isn't actually using directly.

like image 123
SteveMcQwark Avatar answered Dec 26 '22 00:12

SteveMcQwark