Search code examples
rusttypestraits

"The value of the associated type must be specified"


I am writing a command line Task management app to teach myself Rust.

So far I have a sqllite and a memory datasource.

pub struct TaskManager {
    source: Datasource, // here rustc complains
}

The manager has a reference to a Datasource, which is a trait:

pub trait Datasource {
    type Settings;

    fn start(&self) -> Result<bool>;
}

Main reads cli args and decides based on them what datasource should be instantiated.

However, Rust tells me

"- rustc: the value of the associated type Settings in source::Datasource must be specified [E0191]"

I understand that types must be specified at compile time, and both sources so far have their types specified.

impl Datasource for SqlLiteDataSource {
    type Settings = SqlLiteSettings;
}

impl Datasource for MemoryDataSource {
    type Settings = MemorySettings;
}

And when parsing the cli args, all arms are evaluated:

    pub fn new(datasource: Datasources) -> Self {
        let ds: Datasource = match datasource {
            Datasources::SqlLite { path } => SqlLiteDataSource::new(path.to_string()),
            _ => MemoryDataSource::new(),
        };
   }

In fact rustc is complaining here as well with the same error.

The idea was that each concrete implementation would have their own settings. How can I then assign a generic trait variable to the TaskManager, so that a backend completes task management depending on the supplied source?


Solution

  • The issue is that you can't put a trait with a type directly into a struct. You would need to use a Boxed trait inside of the TaskManager, because the Rust compiler needs to know a specific type (in this case Settings) for the Datasource. Change the line source: Datasource to either define the Boxed trait with a default Settings type, or another boxed trait. If you have a specific default Settings type you could set it to for compilation you could just change the line to source: Box<dyn Datasource<Settings=ChosenType>> or you could set Settings to a boxed trait as well using the line source: Box<dyn Datasource<Settings=Box<dyn Settings>>>

    This will clarify to the Rust compiler a specified type for the Datasource trait inside of the TaskManager struct.