Reference implementer struct in return type and parameters in trait methods

I am a Rust beginner and I wrote a simple configuration struct for my Rust project.

use std::fs;
use std::path::PathBuf;

use serde::{ Serialize, Deserialize };

const FILENAME: &str = "config.lock";

#[derive(Serialize, Deserialize)]
pub struct Config {
	// todo
}

impl Config {
	fn get_path(exe_path: &PathBuf) -> PathBuf {
		let mut path = exe_path.clone();
		path.push(FILENAME);
		path
	}
	
	pub fn load(path: &PathBuf) -> Config {
		ron::from_str(&fs::read_to_string(Config::get_path(path)).unwrap_or(String::new())).unwrap_or(ron::from_str("").unwrap())
	}
	
	pub fn save(path: &PathBuf, config: &Config) {
		fs::write(Config::get_path(path), ron::to_string(config));
	}
}

But am now struggling because I need a second configuration type; (I want to add a separate configuration for the setup process). Therefore I tried to move the methods into a trait and make them default implementations. My problem is that I have no clue how to replace the Config struct in the return type and parameters above with a type which essentially resolves to the implementer struct.

After trying some different solutions I am clueless. Maybe someone can point me in the right direction or show me a working solution. I would appreciate any help!

I think you need "&self" or "&mut self" as the first param. And to return the Config, you can just return "Self".

pub fn load(path: &PathBuf) -> Self {...}


pub fn save(&self, path: &PathBuf ) {...}

Here's the chapter from the Rust book on structs and methods: https://doc.rust-lang.org/book/ch05-03-method-syntax.html?highlight=method#defining-methods

BTW: &PathBuf is like &String, and it's a type that doesn't make sense. Use &Path for arguments. Or impl AsRef<Path>.

1 Like

Thanks for the tip, unfortunately I already tried that and it does not seem to work. I tried it again just now but the compiler complains. Maybe I did something wrong?

Modified code
use std::fs;
use std::path::{PathBuf, Path};

use serde::{ Serialize, Deserialize };

const FILENAME: &str = "config.lock";

pub trait Configuration {
	fn get_path(exe_path: &Path) -> PathBuf {
		exe_path.join(FILENAME)
	}
	
	fn load(path: &Path) -> Self {
		ron::from_str(&fs::read_to_string(Config::get_path(path)).unwrap_or(String::new())).unwrap_or(ron::from_str("").unwrap())
	}
	
	fn save(path: &Path, config: &Self) {
		fs::write(Config::get_path(path), ron::to_string(config));
	}
}

#[derive(Serialize, Deserialize)]
pub struct Config {
	// todo
}

impl Configuration for Config {}
Compiler output
/home/kern.tobias/.cargo/bin/cargo build --color=always --all --all-targets
   Compiling zephyr v0.1.0 (/home/kern.tobias/Documents/Projects/Zephyr)
error[E0277]: the size for values of type `Self` cannot be known at compilation time
  --> src/server/config.rs:13:26
   |
13 |     fn load(path: &Path) -> Self {
   |                             ^^^^- help: consider further restricting `Self`: `where Self: std::marker::Sized`
   |                             |
   |                             doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `Self`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: the return type of a function must have a statically known size

error[E0277]: the size for values of type `Self` cannot be known at compilation time
  --> src/server/config.rs:14:97
   |
13 |     fn load(path: &Path) -> Self {
   |                                 - help: consider further restricting `Self`: `where Self: std::marker::Sized`
14 |         ron::from_str(&fs::read_to_string(Config::get_path(path)).unwrap_or(String::new())).unwrap_or(ron::from_str("").unwrap())
   |                                                                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `Self`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

error[E0277]: the size for values of type `Self` cannot be known at compilation time
  --> src/server/config.rs:14:115
   |
13 |     fn load(path: &Path) -> Self {
   |                                 - help: consider further restricting `Self`: `where Self: std::marker::Sized`
14 |         ron::from_str(&fs::read_to_string(Config::get_path(path)).unwrap_or(String::new())).unwrap_or(ron::from_str("").unwrap())
   |                                                                                                                         ^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `Self`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

error[E0277]: the trait bound `Self: server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Deserialize<'_>` is not satisfied
  --> src/server/config.rs:14:3
   |
13 |     fn load(path: &Path) -> Self {
   |                                 - help: consider further restricting `Self`: `where Self: server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Deserialize<'_>`
14 |         ron::from_str(&fs::read_to_string(Config::get_path(path)).unwrap_or(String::new())).unwrap_or(ron::from_str("").unwrap())
   |         ^^^^^^^^^^^^^ the trait `server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Deserialize<'_>` is not implemented for `Self`
   | 
  ::: /home/kern.tobias/.cargo/registry/src/github.com-1ecc6299db9ec823/ron-0.6.0/src/de/mod.rs:63:8
   |
63 |     T: de::Deserialize<'a>,
   |        ------------------- required by this bound in `ron::de::from_str`

error[E0277]: the trait bound `Self: server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Deserialize<'_>` is not satisfied
  --> src/server/config.rs:14:97
   |
13 |     fn load(path: &Path) -> Self {
   |                                 - help: consider further restricting `Self`: `where Self: server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Deserialize<'_>`
14 |         ron::from_str(&fs::read_to_string(Config::get_path(path)).unwrap_or(String::new())).unwrap_or(ron::from_str("").unwrap())
   |                                                                                                       ^^^^^^^^^^^^^ the trait `server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Deserialize<'_>` is not implemented for `Self`
   | 
  ::: /home/kern.tobias/.cargo/registry/src/github.com-1ecc6299db9ec823/ron-0.6.0/src/de/mod.rs:63:8
   |
63 |     T: de::Deserialize<'a>,
   |        ------------------- required by this bound in `ron::de::from_str`

error[E0277]: the size for values of type `Self` cannot be known at compilation time
  --> src/server/config.rs:13:26
   |
13 |     fn load(path: &Path) -> Self {
   |                             ^^^^- help: consider further restricting `Self`: `where Self: std::marker::Sized`
   |                             |
   |                             doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `Self`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: the return type of a function must have a statically known size

error[E0277]: the size for values of type `Self` cannot be known at compilation time
  --> src/server/config.rs:18:52
   |
17 |     fn save(path: &Path, config: &Self) {
   |                                        - help: consider further restricting `Self`: `where Self: std::marker::Sized`
18 |         fs::write(Config::get_path(path), ron::to_string(config));
   |                                                          ^^^^^^ doesn't have a size known at compile-time
   | 
  ::: /home/kern.tobias/.cargo/registry/src/github.com-1ecc6299db9ec823/ron-0.6.0/src/ser/mod.rs:23:18
   |
23 | pub fn to_string<T>(value: &T) -> Result<String>
   |                  - required by this bound in `ron::ser::to_string`
   |
   = help: the trait `std::marker::Sized` is not implemented for `Self`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

error[E0277]: the trait bound `Self: server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Serialize` is not satisfied
  --> src/server/config.rs:18:52
   |
17 |     fn save(path: &Path, config: &Self) {
   |                                        - help: consider further restricting `Self`: `where Self: server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Serialize`
18 |         fs::write(Config::get_path(path), ron::to_string(config));
   |                                                          ^^^^^^ the trait `server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Serialize` is not implemented for `Self`
   | 
  ::: /home/kern.tobias/.cargo/registry/src/github.com-1ecc6299db9ec823/ron-0.6.0/src/ser/mod.rs:25:8
   |
25 |     T: Serialize,
   |        --------- required by this bound in `ron::ser::to_string`

error[E0277]: the trait bound `std::result::Result<std::string::String, ron::error::Error>: std::convert::AsRef<[u8]>` is not satisfied
   --> src/server/config.rs:18:37
    |
18  |         fs::write(Config::get_path(path), ron::to_string(config));
    |                                           ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::AsRef<[u8]>` is not implemented for `std::result::Result<std::string::String, ron::error::Error>`

error[E0277]: the size for values of type `Self` cannot be known at compilation time
  --> src/server/config.rs:14:97
   |
13 |     fn load(path: &Path) -> Self {
   |                                 - help: consider further restricting `Self`: `where Self: std::marker::Sized`
14 |         ron::from_str(&fs::read_to_string(Config::get_path(path)).unwrap_or(String::new())).unwrap_or(ron::from_str("").unwrap())
   |                                                                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `Self`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

error[E0277]: the size for values of type `Self` cannot be known at compilation time
  --> src/server/config.rs:14:115
   |
13 |     fn load(path: &Path) -> Self {
   |                                 - help: consider further restricting `Self`: `where Self: std::marker::Sized`
14 |         ron::from_str(&fs::read_to_string(Config::get_path(path)).unwrap_or(String::new())).unwrap_or(ron::from_str("").unwrap())
   |                                                                                                                         ^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `Self`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

error: aborting due to 8 previous errors

For more information about this error, try `rustc --explain E0277`.
error: could not compile `zephyr`.

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error[E0277]: the trait bound `Self: server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Deserialize<'_>` is not satisfied
  --> src/server/config.rs:14:3
   |
13 |     fn load(path: &Path) -> Self {
   |                                 - help: consider further restricting `Self`: `where Self: server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Deserialize<'_>`
14 |         ron::from_str(&fs::read_to_string(Config::get_path(path)).unwrap_or(String::new())).unwrap_or(ron::from_str("").unwrap())
   |         ^^^^^^^^^^^^^ the trait `server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Deserialize<'_>` is not implemented for `Self`
   | 
  ::: /home/kern.tobias/.cargo/registry/src/github.com-1ecc6299db9ec823/ron-0.6.0/src/de/mod.rs:63:8
   |
63 |     T: de::Deserialize<'a>,
   |        ------------------- required by this bound in `ron::de::from_str`

error[E0277]: the trait bound `Self: server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Deserialize<'_>` is not satisfied
  --> src/server/config.rs:14:97
   |
13 |     fn load(path: &Path) -> Self {
   |                                 - help: consider further restricting `Self`: `where Self: server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Deserialize<'_>`
14 |         ron::from_str(&fs::read_to_string(Config::get_path(path)).unwrap_or(String::new())).unwrap_or(ron::from_str("").unwrap())
   |                                                                                                       ^^^^^^^^^^^^^ the trait `server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Deserialize<'_>` is not implemented for `Self`
   | 
  ::: /home/kern.tobias/.cargo/registry/src/github.com-1ecc6299db9ec823/ron-0.6.0/src/de/mod.rs:63:8
   |
63 |     T: de::Deserialize<'a>,
   |        ------------------- required by this bound in `ron::de::from_str`

error[E0277]: the size for values of type `Self` cannot be known at compilation time
  --> src/server/config.rs:18:52
   |
17 |     fn save(path: &Path, config: &Self) {
   |                                        - help: consider further restricting `Self`: `where Self: std::marker::Sized`
18 |         fs::write(Config::get_path(path), ron::to_string(config));
   |                                                          ^^^^^^ doesn't have a size known at compile-time
   | 
  ::: /home/kern.tobias/.cargo/registry/src/github.com-1ecc6299db9ec823/ron-0.6.0/src/ser/mod.rs:23:18
   |
23 | pub fn to_string<T>(value: &T) -> Result<String>
   |                  - required by this bound in `ron::ser::to_string`
   |
   = help: the trait `std::marker::Sized` is not implemented for `Self`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

error[E0277]: the trait bound `Self: server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Serialize` is not satisfied
  --> src/server/config.rs:18:52
   |
17 |     fn save(path: &Path, config: &Self) {
   |                                        - help: consider further restricting `Self`: `where Self: server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Serialize`
18 |         fs::write(Config::get_path(path), ron::to_string(config));
   |                                                          ^^^^^^ the trait `server::config::_IMPL_DESERIALIZE_FOR_Config::_serde::Serialize` is not implemented for `Self`
   | 
  ::: /home/kern.tobias/.cargo/registry/src/github.com-1ecc6299db9ec823/ron-0.6.0/src/ser/mod.rs:25:8
   |
25 |     T: Serialize,
   |        --------- required by this bound in `ron::ser::to_string`

error[E0277]: the trait bound `std::result::Result<std::string::String, ron::error::Error>: std::convert::AsRef<[u8]>` is not satisfied
   --> src/server/config.rs:18:37
    |
18  |         fs::write(Config::get_path(path), ron::to_string(config));
    |                                           ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::AsRef<[u8]>` is not implemented for `std::result::Result<std::string::String, ron::error::Error>`

error: aborting due to 8 previous errors

For more information about this error, try `rustc --explain E0277`.
error: could not compile `zephyr`.

To learn more, run the command again with --verbose.

Process finished with exit code 101

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.