Path is an unsized type, meaning that it must always be used behind a pointer like & or Box. The owned version of this type is PathBuf. PathBuf implements Deref to Path, so you can use all of its methods. This explains why you cannot return Path.
Now why can't you return &Path from your method? Have a look at join: Creates an owned PathBuf with path adjoined to self. So you create a new PathBuf in your method and return a reference to it. But this new one will be dropped as soon as the method ends and the PathBuf goes out of scope. You also currently take ownership of self, so this would drop the PathBuf even if you do not create a new one but just push to it.
So how would solutions look like? Assuming you do not want to modify the PathBuf in Deploy, you'd simply return an owned PathBuf.
use std::path::Path;
use std::path::PathBuf;
struct Deploy(PathBuf);
impl Deploy {
fn values_yaml(&self) -> PathBuf {
self.0.join("helm").join("chart").join("values.yaml")
}
}
fn main() {
let s = r"/etc";
let deploy = Deploy(PathBuf::from(s));
let values_yaml = deploy.values_yaml();
i_take_a_path(&values_yaml);
}
fn i_take_a_path(path: &Path) {
println!("{:?}", path);
}
If you really want to modify the underlying PathBuf of Deploy, you'd go with that:
use std::path::Path;
use std::path::PathBuf;
struct Deploy(PathBuf);
impl Deploy {
fn values_yaml(&mut self) -> &Path {
self.0.push("helm");
self.0.push("chart");
self.0.push("values.yaml");
self.0.as_path()
}
}
fn main() {
let s = r"/etc";
let mut deploy = Deploy(PathBuf::from(s));
let values_yaml = deploy.values_yaml();
i_take_a_path(values_yaml);
}
fn i_take_a_path(path: &Path) {
println!("{:?}", path);
}
This time the reference works, because it is directly pointing to the PathBuf in Deploy, and not a newly created one.