Skip to content

Commit

Permalink
Auto merge of #76781 - RalfJung:rollup-ve66o2j, r=RalfJung
Browse files Browse the repository at this point in the history
Rollup of 10 pull requests

Successful merges:

 - #76056 (Add more info for Vec Drain doc)
 - #76062 (Vec slice example fix style and show type elision)
 - #76262 (Use inline(never) instead of cold)
 - #76335 (Make all methods of `Duration` unstably const)
 - #76366 (Add Arith Tests in Library)
 - #76369 (Move Various str tests in library)
 - #76534 (Add doc comments for From impls)
 - #76622 (Update bootstrap readme)
 - #76641 (Some cleanup changes and commenting)
 - #76662 (Fix liballoc test suite for Miri)

Failed merges:

r? `@ghost`
  • Loading branch information
bors committed Sep 16, 2020
2 parents 1e11660 + 9d0a265 commit 5fae569
Show file tree
Hide file tree
Showing 26 changed files with 292 additions and 274 deletions.
6 changes: 6 additions & 0 deletions compiler/rustc_middle/src/ty/sty.rs
Expand Up @@ -2280,6 +2280,12 @@ impl<'tcx> TyS<'tcx> {
///
/// Returning true means the type is known to be sized. Returning
/// `false` means nothing -- could be sized, might not be.
///
/// Note that we could never rely on the fact that a type such as `[_]` is
/// trivially `!Sized` because we could be in a type environment with a
/// bound such as `[_]: Copy`. A function with such a bound obviously never
/// can be called, but that doesn't mean it shouldn't typecheck. This is why
/// this method doesn't return `Option<bool>`.
pub fn is_trivially_sized(&self, tcx: TyCtxt<'tcx>) -> bool {
match self.kind() {
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
Expand Down
Expand Up @@ -1512,12 +1512,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
// avoid inundating the user with unnecessary errors, but we now
// check upstream for type errors and don't add the obligations to
// begin with in those cases.
if self
.tcx
.lang_items()
.sized_trait()
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
{
if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
return;
}
Expand Down
20 changes: 5 additions & 15 deletions compiler/rustc_traits/src/chalk/db.rs
Expand Up @@ -110,25 +110,15 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
.map(|i| chalk_ir::AssocTypeId(i.def_id))
.collect();

let well_known = if self
.interner
.tcx
.lang_items()
.sized_trait()
.map(|t| def_id == t)
.unwrap_or(false)
{
let well_known = if self.interner.tcx.lang_items().sized_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::Sized)
} else if self.interner.tcx.lang_items().copy_trait().map(|t| def_id == t).unwrap_or(false)
{
} else if self.interner.tcx.lang_items().copy_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::Copy)
} else if self.interner.tcx.lang_items().clone_trait().map(|t| def_id == t).unwrap_or(false)
{
} else if self.interner.tcx.lang_items().clone_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::Clone)
} else if self.interner.tcx.lang_items().drop_trait().map(|t| def_id == t).unwrap_or(false)
{
} else if self.interner.tcx.lang_items().drop_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::Drop)
} else if self.interner.tcx.lang_items().fn_trait().map(|t| def_id == t).unwrap_or(false) {
} else if self.interner.tcx.lang_items().fn_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::Fn)
} else if self
.interner
Expand Down
4 changes: 4 additions & 0 deletions library/alloc/src/collections/binary_heap.rs
Expand Up @@ -1343,6 +1343,10 @@ impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {

#[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
impl<T> From<BinaryHeap<T>> for Vec<T> {
/// Converts a `BinaryHeap<T>` into a `Vec<T>`.
///
/// This conversion requires no data movement or allocation, and has
/// constant time complexity.
fn from(heap: BinaryHeap<T>) -> Vec<T> {
heap.data
}
Expand Down
6 changes: 1 addition & 5 deletions library/alloc/src/collections/vec_deque.rs
Expand Up @@ -1089,11 +1089,7 @@ impl<T> VecDeque<T> {
where
R: RangeBounds<usize>,
{
// SAFETY: This buffer is only used to check the range. It might be partially
// uninitialized, but `check_range` needs a contiguous slice.
// https://github.com/rust-lang/rust/pull/75207#discussion_r471193682
let buffer = unsafe { slice::from_raw_parts(self.ptr(), self.len()) };
let Range { start, end } = buffer.check_range(range);
let Range { start, end } = slice::check_range(self.len(), range);
let tail = self.wrap_add(self.tail, start);
let head = self.wrap_add(self.tail, end);
(tail, head)
Expand Down
2 changes: 2 additions & 0 deletions library/alloc/src/slice.rs
Expand Up @@ -91,6 +91,8 @@ use crate::borrow::ToOwned;
use crate::boxed::Box;
use crate::vec::Vec;

#[unstable(feature = "slice_check_range", issue = "76393")]
pub use core::slice::check_range;
#[unstable(feature = "array_chunks", issue = "74985")]
pub use core::slice::ArrayChunks;
#[unstable(feature = "array_chunks", issue = "74985")]
Expand Down
3 changes: 2 additions & 1 deletion library/alloc/src/string.rs
Expand Up @@ -49,6 +49,7 @@ use core::iter::{FromIterator, FusedIterator};
use core::ops::Bound::{Excluded, Included, Unbounded};
use core::ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds};
use core::ptr;
use core::slice;
use core::str::{lossy, pattern::Pattern};

use crate::borrow::{Cow, ToOwned};
Expand Down Expand Up @@ -1506,7 +1507,7 @@ impl String {
// of the vector version. The data is just plain bytes.
// Because the range removal happens in Drop, if the Drain iterator is leaked,
// the removal will not happen.
let Range { start, end } = self.as_bytes().check_range(range);
let Range { start, end } = slice::check_range(self.len(), range);
assert!(self.is_char_boundary(start));
assert!(self.is_char_boundary(end));

Expand Down
7 changes: 5 additions & 2 deletions library/alloc/src/vec.rs
Expand Up @@ -174,7 +174,9 @@ use crate::raw_vec::RawVec;
///
/// // ... and that's all!
/// // you can also do it like this:
/// let x : &[usize] = &v;
/// let u: &[usize] = &v;
/// // or like this:
/// let u: &[_] = &v;
/// ```
///
/// In Rust, it's more common to pass slices as arguments rather than vectors
Expand Down Expand Up @@ -1310,7 +1312,7 @@ impl<T> Vec<T> {
// the hole, and the vector length is restored to the new length.
//
let len = self.len();
let Range { start, end } = self.check_range(range);
let Range { start, end } = slice::check_range(len, range);

unsafe {
// set self.vec length's to start, to be safe in case Drain is leaked
Expand Down Expand Up @@ -3037,6 +3039,7 @@ impl<T> AsIntoIter for IntoIter<T> {
/// A draining iterator for `Vec<T>`.
///
/// This `struct` is created by [`Vec::drain`].
/// See its documentation for more.
#[stable(feature = "drain", since = "1.6.0")]
pub struct Drain<'a, T: 'a> {
/// Index of tail to preserve
Expand Down
21 changes: 21 additions & 0 deletions library/alloc/tests/str.rs
Expand Up @@ -1921,3 +1921,24 @@ fn different_str_pattern_forwarding_lifetimes() {

foo::<&str>("x");
}

#[test]
fn test_str_multiline() {
let a: String = "this \
is a test"
.to_string();
let b: String = "this \
is \
another \
test"
.to_string();
assert_eq!(a, "this is a test".to_string());
assert_eq!(b, "this is another test".to_string());
}

#[test]
fn test_str_escapes() {
let x = "\\\\\
";
assert_eq!(x, r"\\"); // extraneous whitespace stripped
}
2 changes: 1 addition & 1 deletion library/alloc/tests/vec.rs
Expand Up @@ -919,7 +919,7 @@ fn test_from_iter_partially_drained_in_place_specialization() {
#[test]
fn test_from_iter_specialization_with_iterator_adapters() {
fn assert_in_place_trait<T: InPlaceIterable>(_: &T) {};
let src: Vec<usize> = vec![0usize; 65535];
let src: Vec<usize> = vec![0usize; 256];
let srcptr = src.as_ptr();
let iter = src
.into_iter()
Expand Down
75 changes: 74 additions & 1 deletion library/core/src/slice/index.rs
@@ -1,6 +1,6 @@
//! Indexing implementations for `[T]`.

use crate::ops;
use crate::ops::{self, Bound, Range, RangeBounds};
use crate::ptr;

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -62,6 +62,79 @@ pub(super) fn slice_end_index_overflow_fail() -> ! {
panic!("attempted to index slice up to maximum usize");
}

/// Performs bounds-checking of the given range.
/// The returned [`Range`] is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`]
/// for slices of the given length.
///
/// [`get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
/// [`get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
///
/// # Panics
///
/// Panics if the range is out of bounds.
///
/// # Examples
///
/// ```
/// #![feature(slice_check_range)]
/// use std::slice;
///
/// let v = [10, 40, 30];
/// assert_eq!(1..2, slice::check_range(v.len(), 1..2));
/// assert_eq!(0..2, slice::check_range(v.len(), ..2));
/// assert_eq!(1..3, slice::check_range(v.len(), 1..));
/// ```
///
/// Panics when [`Index::index`] would panic:
///
/// ```should_panic
/// #![feature(slice_check_range)]
///
/// std::slice::check_range(3, 2..1);
/// ```
///
/// ```should_panic
/// #![feature(slice_check_range)]
///
/// std::slice::check_range(3, 1..4);
/// ```
///
/// ```should_panic
/// #![feature(slice_check_range)]
///
/// std::slice::check_range(3, 1..=usize::MAX);
/// ```
///
/// [`Index::index`]: ops::Index::index
#[track_caller]
#[unstable(feature = "slice_check_range", issue = "76393")]
pub fn check_range<R: RangeBounds<usize>>(len: usize, range: R) -> Range<usize> {
let start = match range.start_bound() {
Bound::Included(&start) => start,
Bound::Excluded(start) => {
start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
}
Bound::Unbounded => 0,
};

let end = match range.end_bound() {
Bound::Included(end) => {
end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
}
Bound::Excluded(&end) => end,
Bound::Unbounded => len,
};

if start > end {
slice_index_order_fail(start, end);
}
if end > len {
slice_end_index_len_fail(end, len);
}

Range { start, end }
}

mod private_slice_index {
use super::ops;
#[stable(feature = "slice_get_slice", since = "1.28.0")]
Expand Down
81 changes: 4 additions & 77 deletions library/core/src/slice/mod.rs
Expand Up @@ -12,7 +12,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less};
use crate::intrinsics::assume;
use crate::marker::{self, Copy};
use crate::mem;
use crate::ops::{Bound, FnMut, Range, RangeBounds};
use crate::ops::{FnMut, Range, RangeBounds};
use crate::option::Option;
use crate::option::Option::{None, Some};
use crate::ptr::{self, NonNull};
Expand Down Expand Up @@ -72,8 +72,8 @@ pub use sort::heapsort;
#[stable(feature = "slice_get_slice", since = "1.28.0")]
pub use index::SliceIndex;

use index::{slice_end_index_len_fail, slice_index_order_fail};
use index::{slice_end_index_overflow_fail, slice_start_index_overflow_fail};
#[unstable(feature = "slice_check_range", issue = "76393")]
pub use index::check_range;

#[lang = "slice"]
#[cfg(not(test))]
Expand Down Expand Up @@ -378,79 +378,6 @@ impl<T> [T] {
unsafe { &mut *index.get_unchecked_mut(self) }
}

/// Converts a range over this slice to [`Range`].
///
/// The returned range is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`].
///
/// [`get_unchecked`]: #method.get_unchecked
/// [`get_unchecked_mut`]: #method.get_unchecked_mut
///
/// # Panics
///
/// Panics if the range is out of bounds.
///
/// # Examples
///
/// ```
/// #![feature(slice_check_range)]
///
/// let v = [10, 40, 30];
/// assert_eq!(1..2, v.check_range(1..2));
/// assert_eq!(0..2, v.check_range(..2));
/// assert_eq!(1..3, v.check_range(1..));
/// ```
///
/// Panics when [`Index::index`] would panic:
///
/// ```should_panic
/// #![feature(slice_check_range)]
///
/// [10, 40, 30].check_range(2..1);
/// ```
///
/// ```should_panic
/// #![feature(slice_check_range)]
///
/// [10, 40, 30].check_range(1..4);
/// ```
///
/// ```should_panic
/// #![feature(slice_check_range)]
///
/// [10, 40, 30].check_range(1..=usize::MAX);
/// ```
///
/// [`Index::index`]: crate::ops::Index::index
#[track_caller]
#[unstable(feature = "slice_check_range", issue = "76393")]
pub fn check_range<R: RangeBounds<usize>>(&self, range: R) -> Range<usize> {
let start = match range.start_bound() {
Bound::Included(&start) => start,
Bound::Excluded(start) => {
start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
}
Bound::Unbounded => 0,
};

let len = self.len();
let end = match range.end_bound() {
Bound::Included(end) => {
end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
}
Bound::Excluded(&end) => end,
Bound::Unbounded => len,
};

if start > end {
slice_index_order_fail(start, end);
}
if end > len {
slice_end_index_len_fail(end, len);
}

Range { start, end }
}

/// Returns a raw pointer to the slice's buffer.
///
/// The caller must ensure that the slice outlives the pointer this
Expand Down Expand Up @@ -2794,7 +2721,7 @@ impl<T> [T] {
where
T: Copy,
{
let Range { start: src_start, end: src_end } = self.check_range(src);
let Range { start: src_start, end: src_end } = check_range(self.len(), src);
let count = src_end - src_start;
assert!(dest <= self.len() - count, "dest is out of bounds");
// SAFETY: the conditions for `ptr::copy` have all been checked above,
Expand Down
8 changes: 8 additions & 0 deletions library/core/src/task/poll.rs
Expand Up @@ -112,6 +112,14 @@ impl<T, E> Poll<Option<Result<T, E>>> {

#[stable(feature = "futures_api", since = "1.36.0")]
impl<T> From<T> for Poll<T> {
/// Convert to a `Ready` variant.
///
/// # Example
///
/// ```
/// # use core::task::Poll;
/// assert_eq!(Poll::from(true), Poll::Ready(true));
/// ```
fn from(t: T) -> Poll<T> {
Poll::Ready(t)
}
Expand Down

0 comments on commit 5fae569

Please sign in to comment.