From 778d5f2074b05c013e15fabc25daf4e37a174bf7 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Sat, 9 Sep 2017 16:48:40 -0400 Subject: [PATCH 01/23] Add Cow -> Box impls. --- src/libstd/error.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 401552a6ec417..6d64ea0d50332 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -53,6 +53,7 @@ use alloc::allocator; use any::TypeId; +use borrow::Cow; use cell; use char; use fmt::{self, Debug, Display}; @@ -217,6 +218,20 @@ impl<'a> From<&'a str> for Box { } } +#[stable(feature = "cow_box_error", since = "1.22.0")] +impl<'a, 'b> From> for Box { + fn from(err: Cow<'b, str>) -> Box { + From::from(String::from(err)) + } +} + +#[stable(feature = "cow_box_error", since = "1.22.0")] +impl<'a> From> for Box { + fn from(err: Cow<'a, str>) -> Box { + From::from(String::from(err)) + } +} + #[unstable(feature = "never_type_impls", issue = "35121")] impl Error for ! { fn description(&self) -> &str { *self } From 7859c9ef442055c477e7788a74f971ac68e8bd67 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Sun, 17 Sep 2017 10:19:11 +0200 Subject: [PATCH 02/23] std: Document thread builder panics for nul bytes in thread names This seems to have been undocumented. Mention this where the name is set (Builder::name) and where the panic could happen (Builder::spawn). Thread::new is private and I think the builder is the only user where this matters. A short comment was added to "document" Thread::new too. --- src/libstd/thread/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 4912ff93abdb3..a084c7fbce157 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -287,6 +287,8 @@ impl Builder { /// Names the thread-to-be. Currently the name is used for identification /// only in panic messages. /// + /// The name must not contain null bytes (`\0`). + /// /// For more information about named threads, see /// [this module-level documentation][naming-threads]. /// @@ -355,6 +357,10 @@ impl Builder { /// [`io::Result`]: ../../std/io/type.Result.html /// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// /// # Examples /// /// ``` @@ -941,6 +947,7 @@ pub struct Thread { impl Thread { // Used only internally to construct a thread object without spawning + // Panics if the name contains nuls. pub(crate) fn new(name: Option) -> Thread { let cname = name.map(|n| { CString::new(n).expect("thread name may not contain interior null bytes") From 7b932d2e127b3b694e8cd2a6ae30d78cc3436547 Mon Sep 17 00:00:00 2001 From: Michal Budzynski Date: Sun, 17 Sep 2017 01:42:15 +0200 Subject: [PATCH 03/23] stabilized vec_splice (fixes #32310) --- .../unstable-book/src/library-features/splice.md | 6 +++--- src/liballoc/vec.rs | 13 ++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/doc/unstable-book/src/library-features/splice.md b/src/doc/unstable-book/src/library-features/splice.md index dae4475257a02..f2d32c8803876 100644 --- a/src/doc/unstable-book/src/library-features/splice.md +++ b/src/doc/unstable-book/src/library-features/splice.md @@ -6,8 +6,8 @@ The tracking issue for this feature is: [#32310] ------------------------ -The `splice()` method on `Vec` and `String` allows you to replace a range -of values in a vector or string with another range of values, and returns +The `splice()` method on `String` allows you to replace a range +of values in a string with another range of values, and returns the replaced values. A simple example: @@ -20,4 +20,4 @@ let beta_offset = s.find('β').unwrap_or(s.len()); // Replace the range up until the β from the string s.splice(..beta_offset, "Α is capital alpha; "); assert_eq!(s, "Α is capital alpha; β is beta"); -``` \ No newline at end of file +``` diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 45574bad9ac07..75d54b8207606 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1943,7 +1943,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(splice)] /// let mut v = vec![1, 2, 3]; /// let new = [7, 8]; /// let u: Vec<_> = v.splice(..2, new.iter().cloned()).collect(); @@ -1951,7 +1950,7 @@ impl Vec { /// assert_eq!(u, &[1, 2]); /// ``` #[inline] - #[unstable(feature = "splice", reason = "recently added", issue = "32310")] + #[stable(feature = "vec_splice", since = "1.22.0")] pub fn splice(&mut self, range: R, replace_with: I) -> Splice where R: RangeArgument, I: IntoIterator { @@ -2554,13 +2553,13 @@ impl<'a, T> InPlace for PlaceBack<'a, T> { /// [`splice()`]: struct.Vec.html#method.splice /// [`Vec`]: struct.Vec.html #[derive(Debug)] -#[unstable(feature = "splice", reason = "recently added", issue = "32310")] +#[stable(feature = "vec_splice", since = "1.22.0")] pub struct Splice<'a, I: Iterator + 'a> { drain: Drain<'a, I::Item>, replace_with: I, } -#[unstable(feature = "splice", reason = "recently added", issue = "32310")] +#[stable(feature = "vec_splice", since = "1.22.0")] impl<'a, I: Iterator> Iterator for Splice<'a, I> { type Item = I::Item; @@ -2573,18 +2572,18 @@ impl<'a, I: Iterator> Iterator for Splice<'a, I> { } } -#[unstable(feature = "splice", reason = "recently added", issue = "32310")] +#[stable(feature = "vec_splice", since = "1.22.0")] impl<'a, I: Iterator> DoubleEndedIterator for Splice<'a, I> { fn next_back(&mut self) -> Option { self.drain.next_back() } } -#[unstable(feature = "splice", reason = "recently added", issue = "32310")] +#[stable(feature = "vec_splice", since = "1.22.0")] impl<'a, I: Iterator> ExactSizeIterator for Splice<'a, I> {} -#[unstable(feature = "splice", reason = "recently added", issue = "32310")] +#[stable(feature = "vec_splice", since = "1.22.0")] impl<'a, I: Iterator> Drop for Splice<'a, I> { fn drop(&mut self) { // exhaust drain first From 6b167f98d9dcfef79519d79d03930062215158fc Mon Sep 17 00:00:00 2001 From: Michal Budzynski Date: Sun, 17 Sep 2017 10:41:24 +0200 Subject: [PATCH 04/23] Updated tracking issue for String::splice and its unstable-book entry --- src/doc/unstable-book/src/library-features/splice.md | 7 +++---- src/liballoc/string.rs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/doc/unstable-book/src/library-features/splice.md b/src/doc/unstable-book/src/library-features/splice.md index f2d32c8803876..2e4bb1a5257c9 100644 --- a/src/doc/unstable-book/src/library-features/splice.md +++ b/src/doc/unstable-book/src/library-features/splice.md @@ -1,14 +1,13 @@ # `splice` -The tracking issue for this feature is: [#32310] +The tracking issue for this feature is: [#44643] -[#32310]: https://github.com/rust-lang/rust/issues/32310 +[#44643]: https://github.com/rust-lang/rust/issues/44643 ------------------------ The `splice()` method on `String` allows you to replace a range -of values in a string with another range of values, and returns -the replaced values. +of values in a string with another range of values. A simple example: diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 46b96df1eabd7..6d0bb264df186 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1451,7 +1451,7 @@ impl String { /// s.splice(..beta_offset, "Α is capital alpha; "); /// assert_eq!(s, "Α is capital alpha; β is beta"); /// ``` - #[unstable(feature = "splice", reason = "recently added", issue = "32310")] + #[unstable(feature = "splice", reason = "recently added", issue = "44643")] pub fn splice(&mut self, range: R, replace_with: &str) where R: RangeArgument { From 2633b85ab2c89822d2c227fc9e81c6ec1c0ed9b6 Mon Sep 17 00:00:00 2001 From: Ixrec Date: Sun, 17 Sep 2017 17:03:56 +0100 Subject: [PATCH 05/23] Replace str's transmute() calls with pointer casts After the following conversation in #rust-lang: ``` [14:43:50] TIL the implementation of from_utf_unchecked is literally just "mem::transmute(x)" [14:43:59] no wonder people keep saying transmute is overpowered [15:15:30] Ixrec: it should be a pointer cast lol [15:15:46] unless it doesn't let you [16:50:34] https://play.rust-lang.org/?gist=d1e6b629ad9ec1baf64ce261c63845e6&version=stable seems like it does let me [16:52:35] Ixrec: yeah that's the preferred impl [16:52:46] Ixrec: it just wasn't in 1.0 [16:52:50] IIRC [16:53:00] (something something fat pointers) ``` Since I already wrote half of the preferred impls in the playground, might as well make an actual PR. --- src/libcore/str/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index d4fef45ae4e8f..60f3640446cab 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -404,7 +404,7 @@ unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { - mem::transmute(v) + &*(v as *const [u8] as *const str) } /// Converts a slice of bytes to a string slice without checking @@ -429,7 +429,7 @@ pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { #[inline] #[stable(feature = "str_mut_extras", since = "1.20.0")] pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { - mem::transmute(v) + &*(v as *mut [u8] as *mut str) } #[stable(feature = "rust1", since = "1.0.0")] @@ -2447,12 +2447,12 @@ impl StrExt for str { #[inline] fn as_bytes(&self) -> &[u8] { - unsafe { mem::transmute(self) } + unsafe { &*(self as *const str as *const [u8]) } } #[inline] unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { - mem::transmute(self) + &mut *(self as *mut str as *mut [u8]) } fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option { From 38fa340ba263612a6f7351d4800d6d4f57ac1cdf Mon Sep 17 00:00:00 2001 From: Ixrec Date: Sun, 17 Sep 2017 17:11:42 +0100 Subject: [PATCH 06/23] missed a 'mut' --- src/libcore/str/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 60f3640446cab..862085c7228af 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -429,7 +429,7 @@ pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { #[inline] #[stable(feature = "str_mut_extras", since = "1.20.0")] pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { - &*(v as *mut [u8] as *mut str) + &mut *(v as *mut [u8] as *mut str) } #[stable(feature = "rust1", since = "1.0.0")] From 2787a285bd211ecbf75fd95d990226242005d848 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 13 Sep 2017 12:20:39 +0200 Subject: [PATCH 07/23] Add `<*const T>::align_offset` and use it in `memchr` --- src/libcore/intrinsics.rs | 33 +-------------- src/libcore/ptr.rs | 75 ++++++++++++++++++++++++++++++++- src/libcore/str/mod.rs | 3 +- src/libstd/lib.rs | 1 + src/libstd/sys_common/memchr.rs | 9 ++-- 5 files changed, 80 insertions(+), 41 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index f7f1dd12d28b1..bc82f0230e5b4 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1381,38 +1381,7 @@ extern "rust-intrinsic" { } #[cfg(stage0)] -/// Computes the byte offset that needs to be applied to `ptr` in order to -/// make it aligned to `align`. -/// If it is not possible to align `ptr`, the implementation returns -/// `usize::max_value()`. -/// -/// There are no guarantees whatsover that offsetting the pointer will not -/// overflow or go beyond the allocation that `ptr` points into. -/// It is up to the caller to ensure that the returned offset is correct -/// in all terms other than alignment. -/// -/// # Examples -/// -/// Accessing adjacent `u8` as `u16` -/// -/// ``` -/// # #![feature(core_intrinsics)] -/// # fn foo(n: usize) { -/// # use std::intrinsics::align_offset; -/// # use std::mem::align_of; -/// # unsafe { -/// let x = [5u8, 6u8, 7u8, 8u8, 9u8]; -/// let ptr = &x[n] as *const u8; -/// let offset = align_offset(ptr as *const (), align_of::()); -/// if offset < x.len() - n - 1 { -/// let u16_ptr = ptr.offset(offset as isize) as *const u16; -/// assert_ne!(*u16_ptr, 500); -/// } else { -/// // while the pointer can be aligned via `offset`, it would point -/// // outside the allocation -/// } -/// # } } -/// ``` +/// remove me after the next release pub unsafe fn align_offset(ptr: *const (), align: usize) -> usize { let offset = ptr as usize % align; if offset == 0 { diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index dd01534ec02d9..4041a3760e5ca 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -1064,7 +1064,43 @@ impl *const T { copy_nonoverlapping(self, dest, count) } - + /// Computes the byte offset that needs to be applied in order to + /// make the pointer aligned to `align`. + /// If it is not possible to align the pointer, the implementation returns + /// `usize::max_value()`. + /// + /// There are no guarantees whatsover that offsetting the pointer will not + /// overflow or go beyond the allocation that the pointer points into. + /// It is up to the caller to ensure that the returned offset is correct + /// in all terms other than alignment. + /// + /// # Examples + /// + /// Accessing adjacent `u8` as `u16` + /// + /// ``` + /// # #![feature(align_offset)] + /// # fn foo(n: usize) { + /// # use std::mem::align_of; + /// # unsafe { + /// let x = [5u8, 6u8, 7u8, 8u8, 9u8]; + /// let ptr = &x[n] as *const u8; + /// let offset = ptr.align_offset(align_of::()); + /// if offset < x.len() - n - 1 { + /// let u16_ptr = ptr.offset(offset as isize) as *const u16; + /// assert_ne!(*u16_ptr, 500); + /// } else { + /// // while the pointer can be aligned via `offset`, it would point + /// // outside the allocation + /// } + /// # } } + /// ``` + #[unstable(feature = "align_offset", issue = "44488")] + pub fn align_offset(self, align: usize) -> usize { + unsafe { + intrinsics::align_offset(self as *const _, align) + } + } } #[lang = "mut_ptr"] @@ -1284,6 +1320,43 @@ impl *mut T { } } + /// Computes the byte offset that needs to be applied in order to + /// make the pointer aligned to `align`. + /// If it is not possible to align the pointer, the implementation returns + /// `usize::max_value()`. + /// + /// There are no guarantees whatsover that offsetting the pointer will not + /// overflow or go beyond the allocation that the pointer points into. + /// It is up to the caller to ensure that the returned offset is correct + /// in all terms other than alignment. + /// + /// # Examples + /// + /// Accessing adjacent `u8` as `u16` + /// + /// ``` + /// # #![feature(align_offset)] + /// # fn foo(n: usize) { + /// # use std::mem::align_of; + /// # unsafe { + /// let x = [5u8, 6u8, 7u8, 8u8, 9u8]; + /// let ptr = &x[n] as *const u8; + /// let offset = ptr.align_offset(align_of::()); + /// if offset < x.len() - n - 1 { + /// let u16_ptr = ptr.offset(offset as isize) as *const u16; + /// assert_ne!(*u16_ptr, 500); + /// } else { + /// // while the pointer can be aligned via `offset`, it would point + /// // outside the allocation + /// } + /// # } } + /// ``` + #[unstable(feature = "align_offset", issue = "44488")] + pub fn align_offset(self, align: usize) -> usize { + unsafe { + intrinsics::align_offset(self as *const _, align) + } + } /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`). /// diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index d4fef45ae4e8f..0d907d11cfba1 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -23,7 +23,6 @@ use fmt; use iter::{Map, Cloned, FusedIterator}; use slice::{self, SliceIndex}; use mem; -use intrinsics::align_offset; pub mod pattern; @@ -1515,7 +1514,7 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { let ptr = v.as_ptr(); let align = unsafe { // the offset is safe, because `index` is guaranteed inbounds - align_offset(ptr.offset(index as isize) as *const (), usize_bytes) + ptr.offset(index as isize).align_offset(usize_bytes) }; if align == 0 { while index < blocks_end { diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 1a0f8b8d2177e..a3eecd46e9051 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -242,6 +242,7 @@ #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] +#![feature(align_offset)] #![feature(asm)] #![feature(box_syntax)] #![feature(cfg_target_has_atomic)] diff --git a/src/libstd/sys_common/memchr.rs b/src/libstd/sys_common/memchr.rs index 3824a5fb5284c..50f998eb4867d 100644 --- a/src/libstd/sys_common/memchr.rs +++ b/src/libstd/sys_common/memchr.rs @@ -65,15 +65,12 @@ pub mod fallback { let usize_bytes = mem::size_of::(); // search up to an aligned boundary - let align = (ptr as usize) & (usize_bytes- 1); - let mut offset; - if align > 0 { - offset = cmp::min(usize_bytes - align, len); + let mut offset = ptr.align_offset(usize_bytes); + if offset > 0 { + offset = cmp::min(offset, len); if let Some(index) = text[..offset].iter().position(|elt| *elt == x) { return Some(index); } - } else { - offset = 0; } // search the body of the text From e47279f51212a749d7cfe1d38a27f10a842d97a5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 17 Sep 2017 22:11:37 +0200 Subject: [PATCH 08/23] Add more links and put the link character to the left --- src/librustdoc/html/render.rs | 8 +++++--- src/librustdoc/html/static/rustdoc.css | 12 ++++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c09ce4c4bd31a..bf0fe5f6e9d98 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2671,8 +2671,9 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, let ns_id = derive_id(format!("{}.{}", field.name.as_ref().unwrap(), ItemType::StructField.name_space())); - write!(w, " -