How do I extract an impl AsRef<Path> value from a Box<dyn AsRef<Path>>?

Christopher Riches

I am using functions from std::fs, which take arguments such as path: impl AsRef<Path>. I wish to make my own functions polymorphic so they too can take any impl AsRef<Path> rather than accepting only &str. However, the path-like object in question must be stored inside one of my structs. This means it must be stored as Box<dyn AsRef<Path>> to give it a known size. I am struggling to convert this boxed value into anything that can be accepted by the std::fs functions.

Consider the following code:

use std::path::Path;

fn main() {
    fn polymorphic(_: impl AsRef<Path>) {}

    let boxed: Box<dyn AsRef<Path>> = Box::new("/foo/bar");
    polymorphic(/*???*/);
}

What do I replace the question marks with to allow me to call polymorphic with "/foo/bar"?

Shepmaster

Dereference and re-reference the Box:

use std::path::Path;

fn main() {
    fn polymorphic(_: impl AsRef<Path>) {}

    let boxed: Box<dyn AsRef<Path>> = Box::new("/foo/bar");
    polymorphic(&*boxed);
}

This means it must be stored as Box<dyn AsRef<Path>>

No it doesn't. The documentation of Path states (emphasis mine):

This is an unsized type, meaning that it must always be used behind a pointer like & or Box. For an owned version of this type, see PathBuf.

use std::path::{Path, PathBuf};

fn polymorphic(_: impl AsRef<Path>) {}

struct Example(PathBuf);

impl Example {
    fn new(path: impl AsRef<Path>) -> Self {
        Self(path.as_ref().to_owned())
    }

    fn example(&self) {
        polymorphic(&self.0)
    }
}

I would actually use Into<PathBuf> myself, as this allows someone to give me ownership of something they no longer need:

use std::path::{Path, PathBuf};

fn polymorphic(_: impl AsRef<Path>) {}

struct Example(PathBuf);

impl Example {
    fn new(path: impl Into<PathBuf>) -> Self {
        Self(path.into())
    }

    fn example(&self) {
        polymorphic(&self.0)
    }
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related