Skip to content

Reduce str transmutes, add mut versions of methods. #41096

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

Merged
merged 1 commit into from
Apr 11, 2017
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions src/doc/unstable-book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@
- [str_checked_slicing](str-checked-slicing.md)
- [str_escape](str-escape.md)
- [str_internals](str-internals.md)
- [str_mut_extras](str-mut-extras.md)
- [struct_field_attributes](struct-field-attributes.md)
- [structural_match](structural-match.md)
- [target_feature](target-feature.md)
Expand Down
8 changes: 8 additions & 0 deletions src/doc/unstable-book/src/str-mut-extras.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# `str_mut_extras`

The tracking issue for this feature is: [#str_mut_extras]

[#str_mut_extras]: https://github.com/rust-lang/rust/issues/41119

------------------------

1 change: 1 addition & 0 deletions src/libcollections/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#![feature(specialization)]
#![feature(staged_api)]
#![feature(str_internals)]
#![feature(str_mut_extras)]
#![feature(trusted_len)]
#![feature(unicode)]
#![feature(unique)]
Expand Down
9 changes: 8 additions & 1 deletion src/libcollections/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub use core::str::{MatchIndices, RMatchIndices};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::str::{from_utf8, Chars, CharIndices, Bytes};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::str::{from_utf8_unchecked, ParseBoolError};
pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError};
#[stable(feature = "rust1", since = "1.0.0")]
pub use std_unicode::str::SplitWhitespace;
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -294,6 +294,13 @@ impl str {
core_str::StrExt::as_bytes(self)
}

/// Converts a mutable string slice to a mutable byte slice.
#[unstable(feature = "str_mut_extras", issue = "41119")]
#[inline(always)]
pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
core_str::StrExt::as_bytes_mut(self)
}

/// Converts a string slice to a raw pointer.
///
/// As string slices are a slice of bytes, the raw pointer points to a
Expand Down
4 changes: 2 additions & 2 deletions src/libcollections/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1790,7 +1790,7 @@ impl ops::IndexMut<ops::RangeFrom<usize>> for String {
impl ops::IndexMut<ops::RangeFull> for String {
#[inline]
fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
unsafe { mem::transmute(&mut *self.vec) }
unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
}
}
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
Expand Down Expand Up @@ -1822,7 +1822,7 @@ impl ops::Deref for String {
impl ops::DerefMut for String {
#[inline]
fn deref_mut(&mut self) -> &mut str {
unsafe { mem::transmute(&mut *self.vec) }
unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/libcore/char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use char_private::is_printable;
use convert::TryFrom;
use fmt::{self, Write};
use slice;
use str::from_utf8_unchecked_mut;
use iter::FusedIterator;
use mem::transmute;

Expand Down Expand Up @@ -448,7 +449,7 @@ impl CharExt for char {
code,
dst.len())
};
transmute(slice::from_raw_parts_mut(dst.as_mut_ptr(), len))
from_utf8_unchecked_mut(dst.get_unchecked_mut(..len))
}
}

Expand Down
39 changes: 32 additions & 7 deletions src/libcore/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use char;
use convert::TryFrom;
use fmt;
use iter::{Map, Cloned, FusedIterator};
use mem;
use slice::{self, SliceIndex};
use mem;

pub mod pattern;

Expand Down Expand Up @@ -300,6 +300,13 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
Ok(unsafe { from_utf8_unchecked(v) })
}

/// Converts a mutable slice of bytes to a mutable string slice.
#[unstable(feature = "str_mut_extras", issue = "41119")]
pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
run_utf8_validation(v)?;
Ok(unsafe { from_utf8_unchecked_mut(v) })
}

/// Forms a str from a pointer and a length.
///
/// The `len` argument is the number of bytes in the string.
Expand All @@ -325,7 +332,7 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
/// str is returned.
///
unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str {
mem::transmute::<&mut [u8], &mut str>(slice::from_raw_parts_mut(p, len))
from_utf8_unchecked_mut(slice::from_raw_parts_mut(p, len))
}

/// Converts a slice of bytes to a string slice without checking
Expand Down Expand Up @@ -365,6 +372,18 @@ pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
mem::transmute(v)
}

/// Converts a slice of bytes to a string slice without checking
/// that the string contains valid UTF-8; mutable version.
///
/// See the immutable version, [`from_utf8_unchecked()`][fromutf8], for more information.
///
/// [fromutf8]: fn.from_utf8_unchecked.html
#[inline(always)]
#[unstable(feature = "str_mut_extras", issue = "41119")]
pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
mem::transmute(v)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Utf8Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down Expand Up @@ -1474,7 +1493,6 @@ Section: Trait implementations
mod traits {
use cmp::Ordering;
use ops;
use mem;
use slice::{self, SliceIndex};
use str::eq_slice;

Expand Down Expand Up @@ -1811,7 +1829,7 @@ mod traits {
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
let ptr = slice.as_ptr().offset(self.start as isize);
let len = self.end - self.start;
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len))
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
Expand Down Expand Up @@ -1859,7 +1877,7 @@ mod traits {
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
let ptr = slice.as_ptr();
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end))
super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, self.end))
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
Expand Down Expand Up @@ -1905,7 +1923,7 @@ mod traits {
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
let ptr = slice.as_ptr().offset(self.start as isize);
let len = slice.len() - self.start;
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len))
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
Expand Down Expand Up @@ -1998,7 +2016,7 @@ mod traits {
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
let ptr = slice.as_ptr();
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end + 1))
super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, self.end + 1))
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
Expand Down Expand Up @@ -2096,6 +2114,8 @@ pub trait StrExt {
fn is_char_boundary(&self, index: usize) -> bool;
#[stable(feature = "core", since = "1.6.0")]
fn as_bytes(&self) -> &[u8];
#[unstable(feature = "str_mut_extras", issue = "0")]
unsafe fn as_bytes_mut(&mut self) -> &mut [u8];
#[stable(feature = "core", since = "1.6.0")]
fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>;
#[stable(feature = "core", since = "1.6.0")]
Expand Down Expand Up @@ -2373,6 +2393,11 @@ impl StrExt for str {
unsafe { mem::transmute(self) }
}

#[inline]
unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
mem::transmute(self)
}

fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
pat.into_searcher(self).next_match().map(|(i, _)| i)
}
Expand Down
5 changes: 2 additions & 3 deletions src/libstd/ascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
#![stable(feature = "rust1", since = "1.0.0")]

use fmt;
use mem;
use ops::Range;
use iter::FusedIterator;

Expand Down Expand Up @@ -599,12 +598,12 @@ impl AsciiExt for str {
}

fn make_ascii_uppercase(&mut self) {
let me: &mut [u8] = unsafe { mem::transmute(self) };
let me = unsafe { self.as_bytes_mut() };
me.make_ascii_uppercase()
}

fn make_ascii_lowercase(&mut self) {
let me: &mut [u8] = unsafe { mem::transmute(self) };
let me = unsafe { self.as_bytes_mut() };
me.make_ascii_lowercase()
}

Expand Down
1 change: 1 addition & 0 deletions src/libstd/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@
#![feature(stmt_expr_attributes)]
#![feature(str_char)]
#![feature(str_internals)]
#![feature(str_mut_extras)]
#![feature(str_utf16)]
#![feature(test, rustc_private)]
#![feature(thread_local)]
Expand Down