Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document From implementations #51753

Merged
merged 7 commits into from
Dec 6, 2018
Merged
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/libstd/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1397,13 +1397,20 @@ impl<'a> From<&'a Path> for Box<Path> {

#[stable(feature = "path_buf_from_box", since = "1.18.0")]
impl From<Box<Path>> for PathBuf {
/// Converts a `Box<Path>` into a `PathBuf`
///
/// This conversion does not allocate or copy memory.
fn from(boxed: Box<Path>) -> PathBuf {
boxed.into_path_buf()
}
}

#[stable(feature = "box_from_path_buf", since = "1.20.0")]
impl From<PathBuf> for Box<Path> {
/// Converts a `PathBuf` into a `Box<Path>`
///
/// This conversion currently should not allocate memory,
// but this behavior is not guaranteed on all platforms or in all future versions.
QuietMisdreavus marked this conversation as resolved.
Show resolved Hide resolved
fn from(p: PathBuf) -> Box<Path> {
p.into_boxed_path()
}
Expand All @@ -1426,20 +1433,29 @@ impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf {

#[stable(feature = "rust1", since = "1.0.0")]
impl From<OsString> for PathBuf {
/// Converts a `OsString` into a `PathBuf`
///
/// This conversion does not allocate or copy memory.
fn from(s: OsString) -> PathBuf {
PathBuf { inner: s }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly, this does not allocate memory. This is free.

PathBuf is a wrapper around OsString. If you have a struct with just one field, its memory structure is the same as the field itself. The Compiler "sees" through this and knows that turning OsString into a PathBuf is effectively a no-op.

See https://godbolt.org/g/1PBCTY (using String, as an example, but the principle is the same). If you have a close look at the blue and orange part, this just sets up for returning the previously allocated String. It doesn't even call the implementation!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for the explanation, was a while since I looked at Assembler. Do you have a general set of tools you use for investigating memory allocation? I sort of did all over the place with no real plan.

}
}

#[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")]
impl From<PathBuf> for OsString {
/// Converts a `PathBuf` into a `OsString`
///
/// This conversion does not allocate or copy memory.
fn from(path_buf : PathBuf) -> OsString {
path_buf.inner
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl From<String> for PathBuf {
/// Converts a `String` into a `PathBuf`
///
/// This conversion does not allocate or copy memory.
fn from(s: String) -> PathBuf {
PathBuf::from(OsString::from(s))
}
Expand Down Expand Up @@ -1536,6 +1552,7 @@ impl<'a> From<Cow<'a, Path>> for PathBuf {

#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<PathBuf> for Arc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
#[inline]
fn from(s: PathBuf) -> Arc<Path> {
let arc: Arc<OsStr> = Arc::from(s.into_os_string());
Expand All @@ -1545,6 +1562,7 @@ impl From<PathBuf> for Arc<Path> {

#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a Path> for Arc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
#[inline]
fn from(s: &Path) -> Arc<Path> {
let arc: Arc<OsStr> = Arc::from(s.as_os_str());
Expand All @@ -1554,6 +1572,7 @@ impl<'a> From<&'a Path> for Arc<Path> {

#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<PathBuf> for Rc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
#[inline]
fn from(s: PathBuf) -> Rc<Path> {
let rc: Rc<OsStr> = Rc::from(s.into_os_string());
Expand All @@ -1563,6 +1582,7 @@ impl From<PathBuf> for Rc<Path> {

#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl<'a> From<&'a Path> for Rc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
#[inline]
fn from(s: &Path) -> Rc<Path> {
let rc: Rc<OsStr> = Rc::from(s.as_os_str());
Expand Down