I have a struct that looks like this:
pub struct MyConfig<P>
{
// Path to file
pub file_path: P,
// Other settings
pub setting1: u8,
// [...]
}
impl <P: AsRef<Path> + std::fmt::Debug> MyConfig<P>
{
pub fn with_path(file_path:: P) -> Result<Self>
{
MyConfig
{
file_path,
setting1: 1
}
}
}
I need a way to clone that config object. I can't just #[derive(Clone)]
, because of the P
trait bound. I tried implementing Clone
manually, but I can't find a way to make a generic copy/clone of the file_path
property. For example, why does this not work:
impl <P: AsRef<Path> + std::fmt::Debug> Clone for MyConfig<P>
{
fn clone(&self) -> Self {
Self { file_path: Path::new(self.file_path.as_ref().file_name()),
setting1: self.setting1.clone(),
}
}
}
I'm quite new to Rust, so maybe this is a really dumb question (or implementation), but I'm really at my wits' end with this - seemingly trivial - problem!
The point of
AsRef<Path>
is to make your public functions more usable, so you can invoke them with values of types&str
,String
,&Path
, andPathBuf
. But there is no reason to hold a value so generic. This applies doubly if you're a novice and unsure of whatAsRef<Path>
does to begin with - in that case, acceptAsRef<Path>
in the public API, and immediately convert it toPathBuf
:Playground
This way you get a fully owned object that can derive
Clone
andDebug
.Remark for advanced usage: When you unconditionally create
PathBuf
, you can alternatively acceptfile_path: impl Into<PathBuf>
, and create the pathbuf withfile_path.into()
. This will accept a similar choice of types likeAsRef<Path>
does, but will avoid a reallocation if the caller passes an ownedString
orPathBuf
. This technique is used e.g. by the fs_err crate to avoid unnecessary allocation.