Skip to content

Commit

Permalink
Inline most of the code paths for conversions with boxed slices
Browse files Browse the repository at this point in the history
This helps with the specific problem described in #49541, obviously without
making any large change to how inlining works in the general case.

Everything involved in the conversions is made `#[inline]`, except for the
`<Vec<T>>::into_boxed_slice` entry point which is made `#[inline(always)]`
after checking that duplicating the function mentioned in the issue prevented
its inlining if I only annotate it with `#[inline]`.

For the record, that function was:

```rust
pub fn foo() -> Box<[u8]> {
    vec![0].into_boxed_slice()
}
```

To help the inliner's job, we also hoist a `self.capacity() != self.len` check
in `<Vec<T>>::shrink_to_fit` and mark it as `#[inline]` too.
  • Loading branch information
nox committed Apr 1, 2018
1 parent 8dd24c8 commit 360f2f0
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,13 +577,15 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> {

#[stable(feature = "box_from_slice", since = "1.17.0")]
impl<'a> From<&'a str> for Box<str> {
#[inline]
fn from(s: &'a str) -> Box<str> {
unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) }
}
}

#[stable(feature = "boxed_str_conv", since = "1.19.0")]
impl From<Box<str>> for Box<[u8]> {
#[inline]
fn from(s: Box<str>) -> Self {
unsafe { Box::from_raw(Box::into_raw(s) as *mut [u8]) }
}
Expand Down
3 changes: 3 additions & 0 deletions src/liballoc/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1811,6 +1811,7 @@ impl str {
/// assert_eq!(*boxed_bytes, *s.as_bytes());
/// ```
#[stable(feature = "str_box_extras", since = "1.20.0")]
#[inline]
pub fn into_boxed_bytes(self: Box<str>) -> Box<[u8]> {
self.into()
}
Expand Down Expand Up @@ -2049,6 +2050,7 @@ impl str {
/// assert_eq!(boxed_str.into_string(), string);
/// ```
#[stable(feature = "box_str", since = "1.4.0")]
#[inline]
pub fn into_string(self: Box<str>) -> String {
let slice = Box::<[u8]>::from(self);
unsafe { String::from_utf8_unchecked(slice.into_vec()) }
Expand Down Expand Up @@ -2307,6 +2309,7 @@ impl str {
/// assert_eq!("☺", &*smile);
/// ```
#[stable(feature = "str_box_extras", since = "1.20.0")]
#[inline]
pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> {
Box::from_raw(Box::into_raw(v) as *mut str)
}
1 change: 1 addition & 0 deletions src/liballoc/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1587,6 +1587,7 @@ impl String {
/// let b = s.into_boxed_str();
/// ```
#[stable(feature = "box_str", since = "1.4.0")]
#[inline]
pub fn into_boxed_str(self) -> Box<str> {
let slice = self.vec.into_boxed_slice();
unsafe { from_boxed_utf8_unchecked(slice) }
Expand Down
6 changes: 5 additions & 1 deletion src/liballoc/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,8 +582,11 @@ impl<T> Vec<T> {
/// assert!(vec.capacity() >= 3);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn shrink_to_fit(&mut self) {
self.buf.shrink_to_fit(self.len);
if self.capacity() != self.len {
self.buf.shrink_to_fit(self.len);
}
}

/// Shrinks the capacity of the vector with a lower bound.
Expand Down Expand Up @@ -636,6 +639,7 @@ impl<T> Vec<T> {
/// assert_eq!(slice.into_vec().capacity(), 3);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline(always)]
pub fn into_boxed_slice(mut self) -> Box<[T]> {
unsafe {
self.shrink_to_fit();
Expand Down

0 comments on commit 360f2f0

Please sign in to comment.