Omar Abid
Omar Abid

Reputation: 15976

Why do I get "use of undeclared type or module" error when calling a struct's function?

I have the following code in Rust:

trait MyTrait {
    fn get_value() -> &'static str;
}

#[derive(Debug)]
struct MyStruct;

impl MyTrait for MyStruct {
    fn get_value() -> &'static str {
        "has value"
    }
}


fn main() {
    println!("My value: {}", MyStruct::get_value());
    has_trait(MyStruct);
}

fn has_trait<T>(trt: T) where T: MyTrait + std::fmt::Debug {
    println!("{:?}", trt)
}

This code is fine. It defines a trait and a struct. The struct implements the trait; which requires to implement a function. Everything is fine until now. But if I try the following code:

trait MyTrait {
    fn get_value() -> &'static str;
}

#[derive(Debug)]
struct MyStruct;

impl MyTrait for MyStruct {
    fn get_value() -> &'static str {
        "has value"
    }
}


fn main() {
    println!("My value: {}", MyStruct::get_value());
    has_trait(MyStruct);
}

fn has_trait<T>(trt: T) where T: MyTrait + std::fmt::Debug {
    println!("{:?}", trt::get_value())
}

I get the following error:

error[E0433]: failed to resolve: use of undeclared type or module `trt`
  --> src/main.rs:21:22
   |
21 |     println!("{:?}", trt::get_value())
   |                      ^^^ use of undeclared type or module `trt`

Now, I don't really understand very well why that wouldn't work. trt should represent a copy of myStruct and then it should have its own functions, right?

Interestingly, this following code will compile:

trait MyTrait {
    fn get_value(&self) -> &'static str;
}

#[derive(Debug)]
struct MyStruct;

impl MyTrait for MyStruct {
    fn get_value(&self) -> &'static str {
        "has value"
    }
}


fn main() {
    println!("My value: {}", MyStruct.get_value());
    has_trait(MyStruct);
}

fn has_trait<T>(trt: T) where T: MyTrait + std::fmt::Debug {
    println!("{:?}", trt.get_value())
}

So what is exactly wrong with the code that doesn't compile?

Upvotes: 2

Views: 4694

Answers (1)

E_net4
E_net4

Reputation: 29972

Now, I don't really understand very well why that wouldn't work. trt should represent a copy of MyStruct and then it should have its own functions, right?

It doesn't quite work that way for associated functions in Rust. With the identifier trt, you can call methods where trt is the receiver (self or one of its variations such as &self or &mut self). However, get_value() does not have a receiver, so it is an associated function. This resembles a static method in some languages such as Java. Unlike Java, associated functions in Rust can only be called by specifying the type or type parameter with that function:

fn has_trait<T>(trt: T) where T: MyTrait + std::fmt::Debug {
    println!("{:?}", T::get_value())
}

This will now work, and would not even need the parameter trt, because we're just calling an associated function of the type T, rather than a method. Although trt is an identifier to a function parameter in this context, the compiler will actually try to interpret it as something else (module name, type name, ...) once combined with the :: token, hence the given error message.

Upvotes: 1

Related Questions