Question about pub module : the trait can't be found in a pub mod

I define a trait and a impl called MyApp:

pub trait app_trait{
    fn run(&self);
}

pub struct MyApp;

impl app_trait for MyApp{
    fn run(&self) {
        println!("My App Run !");
    }
}

then I add it to main and try to call run(), but the run() can't be found

mod app;

fn main() {
    let my_app = app::MyApp {};
    my_app.run();
}

error[E0599]: no method named run found for struct MyApp in the current scope
--> src/main.rs:5:12
|
5 | my_app.run();
| ^^^ method not found in MyApp

I must add a 'use' for this trait in the main file:
use crate::app::app_trait;

The trait 'app_trait' is defined as pub, why can't it be found in the main file?
Actually, I hope that user only know 'MyApp' and not care about the trait.

Traits are only consulted for method lookup if they are in scope — if there is a use for them or a trait bound. You cannot call a method from a trait without mentioning the trait (or a trait with it as a supertrait) somewhere in that file. pub only affects whether it's possible for the trait to be in scope.

If you want my_app.run() to work without mentioning the trait, you must define an inherent method. If you want, that inherent method can just forward to the trait method, or vice versa,

impl MyApp {
    fn run(&self) {
        app_trait::run(self)
    }
}

though that might be confusing.

1 Like

Why do you have that trait in the first place, then? Just implement your method directly for your type, there is no need to add any traits if you don't plan to use them.

This is just sample code. There are different types of App in the real project, the code is like this :

pub trait AppTrait{
    fn run(&self);
}

struct MyApp1;

impl AppTrait for MyApp1{
    fn run(&self) {
        //...
    }
}

struct MyApp2;

impl AppTrait for MyApp2{
    fn run(&self) {
        //...
    }
}

So I hope user don't know about the trait and only care about 'MyApp'.

But I found new question after updating the code, I add a 'Factory' to create the app, and it will return a Box , then the main function could work and I don't need to add the "use crate::app::app_trait"

pub struct AppFactory;

impl AppFactory{
    pub fn create() -> Box<dyn AppTrait>{
        Box::new(MyApp1{})
        // Maybe return MyApp2 or other
    }
}
mod app;

fn main() {
    let my_app = app::AppFactory::create();
    my_app.run();
}

Why "use" is no longer needed after using Box?

Besides use, traits can also be used in situations where they “obviously” should be:

  • the value is of a generic type bounded by that trait (T: AppTrait)
  • the value is a dyn AppTrait

In either of those cases, there aren't any other methods, and it is almost certain that the explicitly involved trait is what matters. So, the compiler makes it available regardless of whether it's used. (This is not a very well documented part of the language.)

3 Likes

Thanks for your answer! This solves my confusion nicely, after I can hardly find any information about this question :+1: