Skip to content

Commit

Permalink
Auto merge of rust-lang#65826 - JohnTitor:rollup-mr6crka, r=JohnTitor
Browse files Browse the repository at this point in the history
Rollup of 6 pull requests

Successful merges:

 - rust-lang#65705 (Add {String,Vec}::into_raw_parts)
 - rust-lang#65749 (Insurance policy in case `iter.size_hint()` lies.)
 - rust-lang#65799 (Fill tracking issue number for `array_value_iter`)
 - rust-lang#65800 (self-profiling: Update measureme to 0.4.0 and remove non-RAII methods from profiler.)
 - rust-lang#65806 (Add [T]::as_ptr_range() and [T]::as_mut_ptr_range().)
 - rust-lang#65810 (SGX: Clear additional flag on enclave entry)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Oct 25, 2019
2 parents 23f890f + d40c6af commit 246be7e
Show file tree
Hide file tree
Showing 12 changed files with 225 additions and 130 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1966,9 +1966,9 @@ dependencies = [

[[package]]
name = "measureme"
version = "0.3.0"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d09de7dafa3aa334bc806447c7e4de69419723312f4b88b80b561dea66601ce8"
checksum = "cd21b0e6e1af976b269ce062038fe5e1b9ca2f817ab7a3af09ec4210aebf0d30"
dependencies = [
"byteorder",
"memmap",
Expand Down
53 changes: 44 additions & 9 deletions src/liballoc/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,20 +196,21 @@ use crate::vec::Vec;
///
/// let story = String::from("Once upon a time...");
///
/// let ptr = story.as_ptr();
// FIXME Update this when vec_into_raw_parts is stabilized
/// // Prevent automatically dropping the String's data
/// let mut story = mem::ManuallyDrop::new(story);
///
/// let ptr = story.as_mut_ptr();
/// let len = story.len();
/// let capacity = story.capacity();
///
/// // story has nineteen bytes
/// assert_eq!(19, len);
///
/// // Now that we have our parts, we throw the story away.
/// mem::forget(story);
///
/// // We can re-build a String out of ptr, len, and capacity. This is all
/// // unsafe because we are responsible for making sure the components are
/// // valid:
/// let s = unsafe { String::from_raw_parts(ptr as *mut _, len, capacity) } ;
/// let s = unsafe { String::from_raw_parts(ptr, len, capacity) } ;
///
/// assert_eq!(String::from("Once upon a time..."), s);
/// ```
Expand Down Expand Up @@ -647,6 +648,37 @@ impl String {
decode_utf16(v.iter().cloned()).map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)).collect()
}

/// Decomposes a `String` into its raw components.
///
/// Returns the raw pointer to the underlying data, the length of
/// the string (in bytes), and the allocated capacity of the data
/// (in bytes). These are the same arguments in the same order as
/// the arguments to [`from_raw_parts`].
///
/// After calling this function, the caller is responsible for the
/// memory previously managed by the `String`. The only way to do
/// this is to convert the raw pointer, length, and capacity back
/// into a `String` with the [`from_raw_parts`] function, allowing
/// the destructor to perform the cleanup.
///
/// [`from_raw_parts`]: #method.from_raw_parts
///
/// # Examples
///
/// ```
/// #![feature(vec_into_raw_parts)]
/// let s = String::from("hello");
///
/// let (ptr, len, cap) = s.into_raw_parts();
///
/// let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) };
/// assert_eq!(rebuilt, "hello");
/// ```
#[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
pub fn into_raw_parts(self) -> (*mut u8, usize, usize) {
self.vec.into_raw_parts()
}

/// Creates a new `String` from a length, capacity, and pointer.
///
/// # Safety
Expand Down Expand Up @@ -677,13 +709,16 @@ impl String {
///
/// unsafe {
/// let s = String::from("hello");
/// let ptr = s.as_ptr();
///
// FIXME Update this when vec_into_raw_parts is stabilized
/// // Prevent automatically dropping the String's data
/// let mut s = mem::ManuallyDrop::new(s);
///
/// let ptr = s.as_mut_ptr();
/// let len = s.len();
/// let capacity = s.capacity();
///
/// mem::forget(s);
///
/// let s = String::from_raw_parts(ptr as *mut _, len, capacity);
/// let s = String::from_raw_parts(ptr, len, capacity);
///
/// assert_eq!(String::from("hello"), s);
/// }
Expand Down
49 changes: 44 additions & 5 deletions src/liballoc/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,44 @@ impl<T> Vec<T> {
}
}

/// Decomposes a `Vec<T>` into its raw components.
///
/// Returns the raw pointer to the underlying data, the length of
/// the vector (in elements), and the allocated capacity of the
/// data (in elements). These are the same arguments in the same
/// order as the arguments to [`from_raw_parts`].
///
/// After calling this function, the caller is responsible for the
/// memory previously managed by the `Vec`. The only way to do
/// this is to convert the raw pointer, length, and capacity back
/// into a `Vec` with the [`from_raw_parts`] function, allowing
/// the destructor to perform the cleanup.
///
/// [`from_raw_parts`]: #method.from_raw_parts
///
/// # Examples
///
/// ```
/// #![feature(vec_into_raw_parts)]
/// let v: Vec<i32> = vec![-1, 0, 1];
///
/// let (ptr, len, cap) = v.into_raw_parts();
///
/// let rebuilt = unsafe {
/// // We can now make changes to the components, such as
/// // transmuting the raw pointer to a compatible type.
/// let ptr = ptr as *mut u32;
///
/// Vec::from_raw_parts(ptr, len, cap)
/// };
/// assert_eq!(rebuilt, [4294967295, 0, 1]);
/// ```
#[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
let mut me = mem::ManuallyDrop::new(self);
(me.as_mut_ptr(), me.len(), me.capacity())
}

/// Creates a `Vec<T>` directly from the raw components of another vector.
///
/// # Safety
Expand Down Expand Up @@ -389,18 +427,19 @@ impl<T> Vec<T> {
/// use std::ptr;
/// use std::mem;
///
/// let mut v = vec![1, 2, 3];
/// let v = vec![1, 2, 3];
///
// FIXME Update this when vec_into_raw_parts is stabilized
/// // Prevent running `v`'s destructor so we are in complete control
/// // of the allocation.
/// let mut v = mem::ManuallyDrop::new(v);
///
/// // Pull out the various important pieces of information about `v`
/// let p = v.as_mut_ptr();
/// let len = v.len();
/// let cap = v.capacity();
///
/// unsafe {
/// // Cast `v` into the void: no destructor run, so we are in
/// // complete control of the allocation to which `p` points.
/// mem::forget(v);
///
/// // Overwrite memory with 4, 5, 6
/// for i in 0..len as isize {
/// ptr::write(p.offset(i), 4 + i);
Expand Down
20 changes: 10 additions & 10 deletions src/libcore/array/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use super::LengthAtMost32;
/// A by-value [array] iterator.
///
/// [array]: ../../std/primitive.array.html
#[unstable(feature = "array_value_iter", issue = "0")]
#[unstable(feature = "array_value_iter", issue = "65798")]
pub struct IntoIter<T, const N: usize>
where
[T; N]: LengthAtMost32,
Expand Down Expand Up @@ -49,7 +49,7 @@ where
/// *Note*: this method might never get stabilized and/or removed in the
/// future as there will likely be another, preferred way of obtaining this
/// iterator (either via `IntoIterator` for arrays or via another way).
#[unstable(feature = "array_value_iter", issue = "0")]
#[unstable(feature = "array_value_iter", issue = "65798")]
pub fn new(array: [T; N]) -> Self {
// The transmute here is actually safe. The docs of `MaybeUninit`
// promise:
Expand Down Expand Up @@ -95,7 +95,7 @@ where
}


#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Iterator for IntoIter<T, {N}>
where
[T; N]: LengthAtMost32,
Expand Down Expand Up @@ -141,7 +141,7 @@ where
}
}

#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, {N}>
where
[T; N]: LengthAtMost32,
Expand Down Expand Up @@ -176,7 +176,7 @@ where
}
}

#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Drop for IntoIter<T, {N}>
where
[T; N]: LengthAtMost32,
Expand All @@ -189,7 +189,7 @@ where
}
}

#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, {N}>
where
[T; N]: LengthAtMost32,
Expand All @@ -204,7 +204,7 @@ where
}
}

#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> FusedIterator for IntoIter<T, {N}>
where
[T; N]: LengthAtMost32,
Expand All @@ -214,13 +214,13 @@ where
// elements (that will still be yielded) is the length of the range `alive`.
// This range is decremented in length in either `next` or `next_back`. It is
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, {N}>
where
[T; N]: LengthAtMost32,
{}

#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: Clone, const N: usize> Clone for IntoIter<T, {N}>
where
[T; N]: LengthAtMost32,
Expand Down Expand Up @@ -251,7 +251,7 @@ where
}
}

#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, {N}>
where
[T; N]: LengthAtMost32,
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::slice::{Iter, IterMut};
mod iter;

#[cfg(not(bootstrap))]
#[unstable(feature = "array_value_iter", issue = "0")]
#[unstable(feature = "array_value_iter", issue = "65798")]
pub use iter::IntoIter;

/// Utility trait implemented only on arrays of fixed size
Expand Down
1 change: 1 addition & 0 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,7 @@ extern "rust-intrinsic" {
/// // the original inner type (`&i32`) to the converted inner type
/// // (`Option<&i32>`), so read the nomicon pages linked above.
/// let v_from_raw = unsafe {
// FIXME Update this when vec_into_raw_parts is stabilized
/// // Ensure the original vector is not dropped.
/// let mut v_clone = std::mem::ManuallyDrop::new(v_clone);
/// Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>,
Expand Down
82 changes: 81 additions & 1 deletion src/libcore/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use crate::fmt;
use crate::intrinsics::{assume, exact_div, unchecked_sub, is_aligned_and_not_null};
use crate::isize;
use crate::iter::*;
use crate::ops::{FnMut, self};
use crate::ops::{FnMut, Range, self};
use crate::option::Option;
use crate::option::Option::{None, Some};
use crate::result::Result;
Expand Down Expand Up @@ -407,6 +407,86 @@ impl<T> [T] {
self as *mut [T] as *mut T
}

/// Returns the two raw pointers spanning the slice.
///
/// The returned range is half-open, which means that the end pointer
/// points *one past* the last element of the slice. This way, an empty
/// slice is represented by two equal pointers, and the difference between
/// the two pointers represents the size of the size.
///
/// See [`as_ptr`] for warnings on using these pointers. The end pointer
/// requires extra caution, as it does not point to a valid element in the
/// slice.
///
/// This function is useful for interacting with foreign interfaces which
/// use two pointers to refer to a range of elements in memory, as is
/// common in C++.
///
/// It can also be useful to check if a pointer to an element refers to an
/// element of this slice:
///
/// ```
/// #![feature(slice_ptr_range)]
///
/// let a = [1, 2, 3];
/// let x = &a[1] as *const _;
/// let y = &5 as *const _;
///
/// assert!(a.as_ptr_range().contains(&x));
/// assert!(!a.as_ptr_range().contains(&y));
/// ```
///
/// [`as_ptr`]: #method.as_ptr
#[unstable(feature = "slice_ptr_range", issue = "65807")]
#[inline]
pub fn as_ptr_range(&self) -> Range<*const T> {
// The `add` here is safe, because:
//
// - Both pointers are part of the same object, as pointing directly
// past the object also counts.
//
// - The size of the slice is never larger than isize::MAX bytes, as
// noted here:
// - https://github.com/rust-lang/unsafe-code-guidelines/issues/102#issuecomment-473340447
// - https://doc.rust-lang.org/reference/behavior-considered-undefined.html
// - https://doc.rust-lang.org/core/slice/fn.from_raw_parts.html#safety
// (This doesn't seem normative yet, but the very same assumption is
// made in many places, including the Index implementation of slices.)
//
// - There is no wrapping around involved, as slices do not wrap past
// the end of the address space.
//
// See the documentation of pointer::add.
let start = self.as_ptr();
let end = unsafe { start.add(self.len()) };
start..end
}

/// Returns the two unsafe mutable pointers spanning the slice.
///
/// The returned range is half-open, which means that the end pointer
/// points *one past* the last element of the slice. This way, an empty
/// slice is represented by two equal pointers, and the difference between
/// the two pointers represents the size of the size.
///
/// See [`as_mut_ptr`] for warnings on using these pointers. The end
/// pointer requires extra caution, as it does not point to a valid element
/// in the slice.
///
/// This function is useful for interacting with foreign interfaces which
/// use two pointers to refer to a range of elements in memory, as is
/// common in C++.
///
/// [`as_mut_ptr`]: #method.as_mut_ptr
#[unstable(feature = "slice_ptr_range", issue = "65807")]
#[inline]
pub fn as_mut_ptr_range(&mut self) -> Range<*mut T> {
// See as_ptr_range() above for why `add` here is safe.
let start = self.as_mut_ptr();
let end = unsafe { start.add(self.len()) };
start..end
}

/// Swaps two elements in the slice.
///
/// # Arguments
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ byteorder = { version = "1.3" }
chalk-engine = { version = "0.9.0", default-features=false }
rustc_fs_util = { path = "../librustc_fs_util" }
smallvec = { version = "0.6.8", features = ["union", "may_dangle"] }
measureme = "0.3"
measureme = "0.4"
6 changes: 5 additions & 1 deletion src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2930,14 +2930,18 @@ impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
// lower bounds from `size_hint` agree they are correct.
Ok(match iter.size_hint() {
(1, Some(1)) => {
f(&[iter.next().unwrap()?])
let t0 = iter.next().unwrap()?;
assert!(iter.next().is_none());
f(&[t0])
}
(2, Some(2)) => {
let t0 = iter.next().unwrap()?;
let t1 = iter.next().unwrap()?;
assert!(iter.next().is_none());
f(&[t0, t1])
}
(0, Some(0)) => {
assert!(iter.next().is_none());
f(&[])
}
_ => {
Expand Down
Loading

0 comments on commit 246be7e

Please sign in to comment.