Auto merge of #81578 - jonas-schievink:rollup-yhiyowl, r=jonas-schievink

Rollup of 18 pull requests

Successful merges:

 - #78044 (Implement io::Seek for io::Empty)
 - #79285 (Stabilize Arc::{increment,decrement}_strong_count)
 - #80053 (stabilise `cargo test -- --include-ignored`)
 - #80279 (Implement missing `AsMut<str>` for `str`)
 - #80470 (Stabilize by-value `[T; N]` iterator `core::array::IntoIter`)
 - #80945 (Add Box::downcast() for dyn Any + Send + Sync)
 - #81048 (Stabilize `core::slice::fill_with`)
 - #81198 (Remove requirement that forces symmetric and transitive PartialEq impls to exist)
 - #81422 (Account for existing `_` field pattern when suggesting `..`)
 - #81472 (Clone entire `TokenCursor` when collecting tokens)
 - #81484 (Optimize decimal formatting of 128-bit integers)
 - #81491 (Balance sidebar `Deref` cycle check with main content)
 - #81509 (Add a regression test for ICE of bad_placeholder_type)
 - #81547 (Edit rustc_typeck top-level docs)
 - #81550 (Replace predecessor with range in collections documentation)
 - #81558 (Fix ascii art text wrapping in mobile)
 - #81562 (Clarify that InPlaceIterable guarantees extend to all advancing iterator methods.)
 - #81563 (Improve docblock readability on small screen)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-01-31 03:05:09 +00:00
commit 7850c28a5f
35 changed files with 282 additions and 116 deletions

View File

@ -11,11 +11,9 @@
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
test(no_crate_inject, attr(deny(warnings))) test(no_crate_inject, attr(deny(warnings)))
)] )]
#![feature(array_value_iter_slice)]
#![feature(dropck_eyepatch)] #![feature(dropck_eyepatch)]
#![feature(new_uninit)] #![feature(new_uninit)]
#![feature(maybe_uninit_slice)] #![feature(maybe_uninit_slice)]
#![feature(array_value_iter)]
#![cfg_attr(bootstrap, feature(min_const_generics))] #![cfg_attr(bootstrap, feature(min_const_generics))]
#![feature(min_specialization)] #![feature(min_specialization)]
#![cfg_attr(test, feature(test))] #![cfg_attr(test, feature(test))]

View File

@ -30,7 +30,6 @@
//! get confused if the spans from leaf AST nodes occur in multiple places //! get confused if the spans from leaf AST nodes occur in multiple places
//! in the HIR, especially for multiple identifiers. //! in the HIR, especially for multiple identifiers.
#![feature(array_value_iter)]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(or_patterns)] #![feature(or_patterns)]
#![recursion_limit = "256"] #![recursion_limit = "256"]

View File

@ -2,7 +2,6 @@
//! //!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
#![feature(array_value_iter)]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(const_fn)] // For the unsizing cast on `&[]` #![feature(const_fn)] // For the unsizing cast on `&[]`
#![feature(const_panic)] #![feature(const_panic)]

View File

@ -1254,15 +1254,7 @@ impl<'a> Parser<'a> {
f: impl FnOnce(&mut Self) -> PResult<'a, (R, TrailingToken)>, f: impl FnOnce(&mut Self) -> PResult<'a, (R, TrailingToken)>,
) -> PResult<'a, R> { ) -> PResult<'a, R> {
let start_token = (self.token.clone(), self.token_spacing); let start_token = (self.token.clone(), self.token_spacing);
let cursor_snapshot = TokenCursor { let cursor_snapshot = self.token_cursor.clone();
frame: self.token_cursor.frame.clone(),
// We only ever capture tokens within our current frame,
// so we can just use an empty frame stack
stack: vec![],
desugar_doc_comments: self.token_cursor.desugar_doc_comments,
num_next_calls: self.token_cursor.num_next_calls,
append_unglued_token: self.token_cursor.append_unglued_token.clone(),
};
let (mut ret, trailing_token) = f(self)?; let (mut ret, trailing_token) = f(self)?;

View File

@ -11,7 +11,6 @@
//! This API is completely unstable and subject to change. //! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(array_value_iter)]
#![feature(bool_to_option)] #![feature(bool_to_option)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(drain_filter)] #![feature(drain_filter)]

View File

@ -52,13 +52,13 @@ The types of top-level items, which never contain unbound type
variables, are stored directly into the `tcx` typeck_results. variables, are stored directly into the `tcx` typeck_results.
N.B., a type variable is not the same thing as a type parameter. A N.B., a type variable is not the same thing as a type parameter. A
type variable is rather an "instance" of a type parameter: that is, type variable is an instance of a type parameter. That is,
given a generic function `fn foo<T>(t: T)`: while checking the given a generic function `fn foo<T>(t: T)`, while checking the
function `foo`, the type `ty_param(0)` refers to the type `T`, which function `foo`, the type `ty_param(0)` refers to the type `T`, which
is treated in abstract. When `foo()` is called, however, `T` will be is treated in abstract. However, when `foo()` is called, `T` will be
substituted for a fresh type variable `N`. This variable will substituted for a fresh type variable `N`. This variable will
eventually be resolved to some concrete type (which might itself be eventually be resolved to some concrete type (which might itself be
type parameter). a type parameter).
*/ */

View File

@ -1041,12 +1041,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
vec![(left, "(".to_string()), (right.shrink_to_hi(), ")".to_string())], vec![(left, "(".to_string()), (right.shrink_to_hi(), ")".to_string())],
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
} else if fields.len() > subpats.len() { } else if fields.len() > subpats.len() && pat_span != DUMMY_SP {
let after_fields_span = if pat_span == DUMMY_SP { let after_fields_span = pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi();
pat_span
} else {
pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi()
};
let all_fields_span = match subpats { let all_fields_span = match subpats {
[] => after_fields_span, [] => after_fields_span,
[field] => field.span, [field] => field.span,
@ -1055,7 +1051,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Check if all the fields in the pattern are wildcards. // Check if all the fields in the pattern are wildcards.
let all_wildcards = subpats.iter().all(|pat| matches!(pat.kind, PatKind::Wild)); let all_wildcards = subpats.iter().all(|pat| matches!(pat.kind, PatKind::Wild));
let first_tail_wildcard =
subpats.iter().enumerate().fold(None, |acc, (pos, pat)| match (acc, &pat.kind) {
(None, PatKind::Wild) => Some(pos),
(Some(_), PatKind::Wild) => acc,
_ => None,
});
let tail_span = match first_tail_wildcard {
None => after_fields_span,
Some(0) => subpats[0].span.to(after_fields_span),
Some(pos) => subpats[pos - 1].span.shrink_to_hi().to(after_fields_span),
};
// FIXME: heuristic-based suggestion to check current types for where to add `_`.
let mut wildcard_sugg = vec!["_"; fields.len() - subpats.len()].join(", "); let mut wildcard_sugg = vec!["_"; fields.len() - subpats.len()].join(", ");
if !subpats.is_empty() { if !subpats.is_empty() {
wildcard_sugg = String::from(", ") + &wildcard_sugg; wildcard_sugg = String::from(", ") + &wildcard_sugg;
@ -1080,7 +1088,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
); );
} else { } else {
err.span_suggestion_verbose( err.span_suggestion_verbose(
after_fields_span, tail_span,
"use `..` to ignore the rest of the fields", "use `..` to ignore the rest of the fields",
String::from(", .."), String::from(", .."),
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,

View File

@ -7,9 +7,9 @@ The type checker is responsible for:
1. Determining the type of each expression. 1. Determining the type of each expression.
2. Resolving methods and traits. 2. Resolving methods and traits.
3. Guaranteeing that most type rules are met. ("Most?", you say, "why most?" 3. Guaranteeing that most type rules are met. ("Most?", you say, "why most?"
Well, dear reader, read on) Well, dear reader, read on.)
The main entry point is `check_crate()`. Type checking operates in The main entry point is [`check_crate()`]. Type checking operates in
several major phases: several major phases:
1. The collect phase first passes over all items and determines their 1. The collect phase first passes over all items and determines their
@ -25,7 +25,7 @@ several major phases:
containing function). Inference is used to supply types wherever containing function). Inference is used to supply types wherever
they are unknown. The actual checking of a function itself has they are unknown. The actual checking of a function itself has
several phases (check, regionck, writeback), as discussed in the several phases (check, regionck, writeback), as discussed in the
documentation for the `check` module. documentation for the [`check`] module.
The type checker is defined into various submodules which are documented The type checker is defined into various submodules which are documented
independently: independently:
@ -56,7 +56,6 @@ This API is completely unstable and subject to change.
*/ */
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(array_value_iter)]
#![feature(bool_to_option)] #![feature(bool_to_option)]
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]

View File

@ -1372,6 +1372,39 @@ impl<A: Allocator> Box<dyn Any + Send, A> {
} }
} }
impl<A: Allocator> Box<dyn Any + Send + Sync, A> {
#[inline]
#[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")]
/// Attempt to downcast the box to a concrete type.
///
/// # Examples
///
/// ```
/// use std::any::Any;
///
/// fn print_if_string(value: Box<dyn Any + Send + Sync>) {
/// if let Ok(string) = value.downcast::<String>() {
/// println!("String ({}): {}", string.len(), string);
/// }
/// }
///
/// let my_string = "Hello World".to_string();
/// print_if_string(Box::new(my_string));
/// print_if_string(Box::new(0i8));
/// ```
pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
if self.is::<T>() {
unsafe {
let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =
Box::into_raw_with_allocator(self);
Ok(Box::from_raw_in(raw as *mut T, alloc))
}
} else {
Err(self)
}
}
}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Display + ?Sized, A: Allocator> fmt::Display for Box<T, A> { impl<T: fmt::Display + ?Sized, A: Allocator> fmt::Display for Box<T, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

View File

@ -78,7 +78,6 @@
#![feature(allocator_api)] #![feature(allocator_api)]
#![feature(array_chunks)] #![feature(array_chunks)]
#![feature(array_methods)] #![feature(array_methods)]
#![feature(array_value_iter)]
#![feature(array_windows)] #![feature(array_windows)]
#![feature(allow_internal_unstable)] #![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)] #![feature(arbitrary_self_types)]

View File

@ -962,15 +962,13 @@ impl<T: ?Sized> Arc<T> {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// #![feature(arc_mutate_strong_count)]
///
/// use std::sync::Arc; /// use std::sync::Arc;
/// ///
/// let five = Arc::new(5); /// let five = Arc::new(5);
/// ///
/// unsafe { /// unsafe {
/// let ptr = Arc::into_raw(five); /// let ptr = Arc::into_raw(five);
/// Arc::incr_strong_count(ptr); /// Arc::increment_strong_count(ptr);
/// ///
/// // This assertion is deterministic because we haven't shared /// // This assertion is deterministic because we haven't shared
/// // the `Arc` between threads. /// // the `Arc` between threads.
@ -979,8 +977,8 @@ impl<T: ?Sized> Arc<T> {
/// } /// }
/// ``` /// ```
#[inline] #[inline]
#[unstable(feature = "arc_mutate_strong_count", issue = "71983")] #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")]
pub unsafe fn incr_strong_count(ptr: *const T) { pub unsafe fn increment_strong_count(ptr: *const T) {
// Retain Arc, but don't touch refcount by wrapping in ManuallyDrop // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop
let arc = unsafe { mem::ManuallyDrop::new(Arc::<T>::from_raw(ptr)) }; let arc = unsafe { mem::ManuallyDrop::new(Arc::<T>::from_raw(ptr)) };
// Now increase refcount, but don't drop new refcount either // Now increase refcount, but don't drop new refcount either
@ -1001,27 +999,25 @@ impl<T: ?Sized> Arc<T> {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// #![feature(arc_mutate_strong_count)]
///
/// use std::sync::Arc; /// use std::sync::Arc;
/// ///
/// let five = Arc::new(5); /// let five = Arc::new(5);
/// ///
/// unsafe { /// unsafe {
/// let ptr = Arc::into_raw(five); /// let ptr = Arc::into_raw(five);
/// Arc::incr_strong_count(ptr); /// Arc::increment_strong_count(ptr);
/// ///
/// // Those assertions are deterministic because we haven't shared /// // Those assertions are deterministic because we haven't shared
/// // the `Arc` between threads. /// // the `Arc` between threads.
/// let five = Arc::from_raw(ptr); /// let five = Arc::from_raw(ptr);
/// assert_eq!(2, Arc::strong_count(&five)); /// assert_eq!(2, Arc::strong_count(&five));
/// Arc::decr_strong_count(ptr); /// Arc::decrement_strong_count(ptr);
/// assert_eq!(1, Arc::strong_count(&five)); /// assert_eq!(1, Arc::strong_count(&five));
/// } /// }
/// ``` /// ```
#[inline] #[inline]
#[unstable(feature = "arc_mutate_strong_count", issue = "71983")] #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")]
pub unsafe fn decr_strong_count(ptr: *const T) { pub unsafe fn decrement_strong_count(ptr: *const T) {
unsafe { mem::drop(Arc::from_raw(ptr)) }; unsafe { mem::drop(Arc::from_raw(ptr)) };
} }

View File

@ -62,7 +62,7 @@ impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for RawWaker {
fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker { fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
// Increment the reference count of the arc to clone it. // Increment the reference count of the arc to clone it.
unsafe fn clone_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) -> RawWaker { unsafe fn clone_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) -> RawWaker {
unsafe { Arc::incr_strong_count(waker as *const W) }; unsafe { Arc::increment_strong_count(waker as *const W) };
RawWaker::new( RawWaker::new(
waker as *const (), waker as *const (),
&RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>), &RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>),
@ -83,7 +83,7 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
// Decrement the reference count of the Arc on drop // Decrement the reference count of the Arc on drop
unsafe fn drop_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) { unsafe fn drop_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) {
unsafe { Arc::decr_strong_count(waker as *const W) }; unsafe { Arc::decrement_strong_count(waker as *const W) };
} }
RawWaker::new( RawWaker::new(

View File

@ -11,7 +11,7 @@ use crate::{
/// A by-value [array] iterator. /// A by-value [array] iterator.
/// ///
/// [array]: ../../std/primitive.array.html /// [array]: ../../std/primitive.array.html
#[unstable(feature = "array_value_iter", issue = "65798")] #[stable(feature = "array_value_iter", since = "1.51.0")]
pub struct IntoIter<T, const N: usize> { pub struct IntoIter<T, const N: usize> {
/// This is the array we are iterating over. /// This is the array we are iterating over.
/// ///
@ -38,10 +38,21 @@ pub struct IntoIter<T, const N: usize> {
impl<T, const N: usize> IntoIter<T, N> { impl<T, const N: usize> IntoIter<T, N> {
/// Creates a new iterator over the given `array`. /// Creates a new iterator over the given `array`.
/// ///
/// *Note*: this method might never get stabilized and/or removed in the /// *Note*: this method might be deprecated in the future,
/// future as there will likely be another, preferred way of obtaining this /// after [`IntoIterator` is implemented for arrays][array-into-iter].
/// iterator (either via `IntoIterator` for arrays or via another way). ///
#[unstable(feature = "array_value_iter", issue = "65798")] /// # Examples
///
/// ```
/// use std::array;
///
/// for value in array::IntoIter::new([1, 2, 3, 4, 5]) {
/// // The type of `value` is a `i32` here, instead of `&i32`
/// let _: i32 = value;
/// }
/// ```
/// [array-into-iter]: https://github.com/rust-lang/rust/pull/65819
#[stable(feature = "array_value_iter", since = "1.51.0")]
pub fn new(array: [T; N]) -> Self { pub fn new(array: [T; N]) -> Self {
// SAFETY: The transmute here is actually safe. The docs of `MaybeUninit` // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
// promise: // promise:
@ -69,7 +80,7 @@ impl<T, const N: usize> IntoIter<T, N> {
/// Returns an immutable slice of all elements that have not been yielded /// Returns an immutable slice of all elements that have not been yielded
/// yet. /// yet.
#[unstable(feature = "array_value_iter_slice", issue = "65798")] #[stable(feature = "array_value_iter", since = "1.51.0")]
pub fn as_slice(&self) -> &[T] { pub fn as_slice(&self) -> &[T] {
// SAFETY: We know that all elements within `alive` are properly initialized. // SAFETY: We know that all elements within `alive` are properly initialized.
unsafe { unsafe {
@ -79,7 +90,7 @@ impl<T, const N: usize> IntoIter<T, N> {
} }
/// Returns a mutable slice of all elements that have not been yielded yet. /// Returns a mutable slice of all elements that have not been yielded yet.
#[unstable(feature = "array_value_iter_slice", issue = "65798")] #[stable(feature = "array_value_iter", since = "1.51.0")]
pub fn as_mut_slice(&mut self) -> &mut [T] { pub fn as_mut_slice(&mut self) -> &mut [T] {
// SAFETY: We know that all elements within `alive` are properly initialized. // SAFETY: We know that all elements within `alive` are properly initialized.
unsafe { unsafe {

View File

@ -18,7 +18,7 @@ use crate::slice::{Iter, IterMut};
mod iter; mod iter;
#[unstable(feature = "array_value_iter", issue = "65798")] #[stable(feature = "array_value_iter", since = "1.51.0")]
pub use iter::IntoIter; pub use iter::IntoIter;
/// Converts a reference to `T` into a reference to an array of length 1 (without copying). /// Converts a reference to `T` into a reference to an array of length 1 (without copying).

View File

@ -31,14 +31,18 @@ use self::Ordering::*;
/// equivalence relation. For example, in floating point numbers `NaN != NaN`, /// equivalence relation. For example, in floating point numbers `NaN != NaN`,
/// so floating point types implement `PartialEq` but not [`trait@Eq`]. /// so floating point types implement `PartialEq` but not [`trait@Eq`].
/// ///
/// Formally, the equality must be (for all `a`, `b` and `c`): /// Formally, the equality must be (for all `a`, `b`, `c` of type `A`, `B`,
/// `C`):
/// ///
/// - symmetric: `a == b` implies `b == a`; and /// - **Symmetric**: if `A: PartialEq<B>` and `B: PartialEq<A>`, then **`a == b`
/// - transitive: `a == b` and `b == c` implies `a == c`. /// implies `b == a`**; and
/// ///
/// Note that these requirements mean that the trait itself must be implemented /// - **Transitive**: if `A: PartialEq<B>` and `B: PartialEq<C>` and `A:
/// symmetrically and transitively: if `T: PartialEq<U>` and `U: PartialEq<V>` /// PartialEq<C>`, then **`a == b` and `b == c` implies `a == c`**.
/// then `U: PartialEq<T>` and `T: PartialEq<V>`. ///
/// Note that the `B: PartialEq<A>` (symmetric) and `A: PartialEq<C>`
/// (transitive) impls are not forced to exist, but these requirements apply
/// whenever they do exist.
/// ///
/// ## Derivable /// ## Derivable
/// ///

View File

@ -616,6 +616,14 @@ impl AsRef<str> for str {
} }
} }
#[stable(feature = "as_mut_str_for_str", since = "1.51.0")]
impl AsMut<str> for str {
#[inline]
fn as_mut(&mut self) -> &mut str {
self
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// THE NO-ERROR ERROR TYPE // THE NO-ERROR ERROR TYPE
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -643,25 +643,42 @@ fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::R
} }
/// Partition of `n` into n > 1e19 and rem <= 1e19 /// Partition of `n` into n > 1e19 and rem <= 1e19
///
/// Integer division algorithm is based on the following paper:
///
/// T. Granlund and P. Montgomery, “Division by Invariant Integers Using Multiplication”
/// in Proc. of the SIGPLAN94 Conference on Programming Language Design and
/// Implementation, 1994, pp. 6172
///
fn udiv_1e19(n: u128) -> (u128, u64) { fn udiv_1e19(n: u128) -> (u128, u64) {
const DIV: u64 = 1e19 as u64; const DIV: u64 = 1e19 as u64;
let high = (n >> 64) as u64; const FACTOR: u128 = 156927543384667019095894735580191660403;
if high == 0 {
let low = n as u64;
return ((low / DIV) as u128, low % DIV);
}
let sr = 65 - high.leading_zeros();
let mut q = n << (128 - sr);
let mut r = n >> sr;
let mut carry = 0;
for _ in 0..sr { let quot = if n < 1 << 83 {
r = (r << 1) | (q >> 127); ((n >> 19) as u64 / (DIV >> 19)) as u128
q = (q << 1) | carry as u128; } else {
u128_mulhi(n, FACTOR) >> 62
};
let s = (DIV as u128).wrapping_sub(r).wrapping_sub(1) as i128 >> 127; let rem = (n - quot * DIV as u128) as u64;
carry = (s & 1) as u64; (quot, rem)
r -= (DIV as u128) & s as u128;
} }
((q << 1) | carry as u128, r as u64)
/// Multiply unsigned 128 bit integers, return upper 128 bits of the result
#[inline]
fn u128_mulhi(x: u128, y: u128) -> u128 {
let x_lo = x as u64;
let x_hi = (x >> 64) as u64;
let y_lo = y as u64;
let y_hi = (y >> 64) as u64;
// handle possibility of overflow
let carry = (x_lo as u128 * y_lo as u128) >> 64;
let m = x_lo as u128 * y_hi as u128 + carry;
let high1 = m >> 64;
let m_lo = m as u64;
let high2 = (x_hi as u128 * y_lo as u128 + m_lo as u128) >> 64;
x_hi as u128 * y_hi as u128 + high1 + high2
} }

View File

@ -43,12 +43,14 @@ unsafe impl<I: TrustedLen + ?Sized> TrustedLen for &mut I {}
/// An iterator that when yielding an item will have taken at least one element /// An iterator that when yielding an item will have taken at least one element
/// from its underlying [`SourceIter`]. /// from its underlying [`SourceIter`].
/// ///
/// Calling [`next()`] guarantees that at least one value of the iterator's underlying source /// Calling any method that advances the iterator, e.g. [`next()`] or [`try_fold()`],
/// has been moved out and the result of the iterator chain could be inserted in its place, /// guarantees that for each step at least one value of the iterator's underlying source
/// assuming structural constraints of the source allow such an insertion. /// has been moved out and the result of the iterator chain could be inserted
/// in its place, assuming structural constraints of the source allow such an insertion.
/// In other words this trait indicates that an iterator pipeline can be collected in place. /// In other words this trait indicates that an iterator pipeline can be collected in place.
/// ///
/// [`SourceIter`]: crate::iter::SourceIter /// [`SourceIter`]: crate::iter::SourceIter
/// [`next()`]: Iterator::next /// [`next()`]: Iterator::next
/// [`try_fold()`]: Iterator::try_fold
#[unstable(issue = "none", feature = "inplace_iteration")] #[unstable(issue = "none", feature = "inplace_iteration")]
pub unsafe trait InPlaceIterable: Iterator {} pub unsafe trait InPlaceIterable: Iterator {}

View File

@ -2852,13 +2852,12 @@ impl<T> [T] {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// #![feature(slice_fill_with)]
///
/// let mut buf = vec![1; 10]; /// let mut buf = vec![1; 10];
/// buf.fill_with(Default::default); /// buf.fill_with(Default::default);
/// assert_eq!(buf, vec![0; 10]); /// assert_eq!(buf, vec![0; 10]);
/// ``` /// ```
#[unstable(feature = "slice_fill_with", issue = "79221")] #[doc(alias = "memset")]
#[stable(feature = "slice_fill_with", since = "1.51.0")]
pub fn fill_with<F>(&mut self, mut f: F) pub fn fill_with<F>(&mut self, mut f: F)
where where
F: FnMut() -> T, F: FnMut() -> T,

View File

@ -50,7 +50,6 @@
#![feature(slice_internals)] #![feature(slice_internals)]
#![feature(slice_partition_dedup)] #![feature(slice_partition_dedup)]
#![feature(int_error_matching)] #![feature(int_error_matching)]
#![feature(array_value_iter)]
#![feature(iter_advance_by)] #![feature(iter_advance_by)]
#![feature(iter_partition_in_place)] #![feature(iter_partition_in_place)]
#![feature(iter_intersperse)] #![feature(iter_intersperse)]

View File

@ -110,8 +110,8 @@
//! //!
//! For Sets, all operations have the cost of the equivalent Map operation. //! For Sets, all operations have the cost of the equivalent Map operation.
//! //!
//! | | get | insert | remove | predecessor | append | //! | | get | insert | remove | range | append |
//! |--------------|-----------|-----------|-----------|-------------|--------| //! |--------------|-----------|-----------|-----------|-----------|--------|
//! | [`HashMap`] | O(1)~ | O(1)~* | O(1)~ | N/A | N/A | //! | [`HashMap`] | O(1)~ | O(1)~* | O(1)~ | N/A | N/A |
//! | [`BTreeMap`] | O(log(n)) | O(log(n)) | O(log(n)) | O(log(n)) | O(n+m) | //! | [`BTreeMap`] | O(log(n)) | O(log(n)) | O(log(n)) | O(log(n)) | O(n+m) |
//! //!

View File

@ -4,7 +4,7 @@
mod tests; mod tests;
use crate::fmt; use crate::fmt;
use crate::io::{self, BufRead, Initializer, IoSlice, IoSliceMut, Read, Write}; use crate::io::{self, BufRead, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
/// A reader which is always at EOF. /// A reader which is always at EOF.
/// ///
@ -58,6 +58,21 @@ impl BufRead for Empty {
fn consume(&mut self, _n: usize) {} fn consume(&mut self, _n: usize) {}
} }
#[stable(feature = "empty_seek", since = "1.51.0")]
impl Seek for Empty {
fn seek(&mut self, _pos: SeekFrom) -> io::Result<u64> {
Ok(0)
}
fn stream_len(&mut self) -> io::Result<u64> {
Ok(0)
}
fn stream_position(&mut self) -> io::Result<u64> {
Ok(0)
}
}
#[stable(feature = "std_debug", since = "1.16.0")] #[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Empty { impl fmt::Debug for Empty {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

View File

@ -1,5 +1,5 @@
use crate::io::prelude::*; use crate::io::prelude::*;
use crate::io::{copy, empty, repeat, sink, Empty, Repeat, Sink}; use crate::io::{copy, empty, repeat, sink, Empty, Repeat, SeekFrom, Sink};
#[test] #[test]
fn copy_copies() { fn copy_copies() {
@ -29,6 +29,26 @@ fn empty_reads() {
assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
} }
#[test]
fn empty_seeks() {
let mut e = empty();
assert!(matches!(e.seek(SeekFrom::Start(0)), Ok(0)));
assert!(matches!(e.seek(SeekFrom::Start(1)), Ok(0)));
assert!(matches!(e.seek(SeekFrom::Start(u64::MAX)), Ok(0)));
assert!(matches!(e.seek(SeekFrom::End(i64::MIN)), Ok(0)));
assert!(matches!(e.seek(SeekFrom::End(-1)), Ok(0)));
assert!(matches!(e.seek(SeekFrom::End(0)), Ok(0)));
assert!(matches!(e.seek(SeekFrom::End(1)), Ok(0)));
assert!(matches!(e.seek(SeekFrom::End(i64::MAX)), Ok(0)));
assert!(matches!(e.seek(SeekFrom::Current(i64::MIN)), Ok(0)));
assert!(matches!(e.seek(SeekFrom::Current(-1)), Ok(0)));
assert!(matches!(e.seek(SeekFrom::Current(0)), Ok(0)));
assert!(matches!(e.seek(SeekFrom::Current(1)), Ok(0)));
assert!(matches!(e.seek(SeekFrom::Current(i64::MAX)), Ok(0)));
}
#[test] #[test]
fn repeat_repeats() { fn repeat_repeats() {
let mut r = repeat(4); let mut r = repeat(4);

View File

@ -230,9 +230,9 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes {
// Unstable flags // Unstable flags
let force_run_in_process = unstable_optflag!(matches, allow_unstable, "force-run-in-process"); let force_run_in_process = unstable_optflag!(matches, allow_unstable, "force-run-in-process");
let exclude_should_panic = unstable_optflag!(matches, allow_unstable, "exclude-should-panic"); let exclude_should_panic = unstable_optflag!(matches, allow_unstable, "exclude-should-panic");
let include_ignored = unstable_optflag!(matches, allow_unstable, "include-ignored");
let time_options = get_time_options(&matches, allow_unstable)?; let time_options = get_time_options(&matches, allow_unstable)?;
let include_ignored = matches.opt_present("include-ignored");
let quiet = matches.opt_present("quiet"); let quiet = matches.opt_present("quiet");
let exact = matches.opt_present("exact"); let exact = matches.opt_present("exact");
let list = matches.opt_present("list"); let list = matches.opt_present("list");

View File

@ -391,12 +391,7 @@ fn parse_show_output_flag() {
#[test] #[test]
fn parse_include_ignored_flag() { fn parse_include_ignored_flag() {
let args = vec![ let args = vec!["progname".to_string(), "filter".to_string(), "--include-ignored".to_string()];
"progname".to_string(),
"filter".to_string(),
"-Zunstable-options".to_string(),
"--include-ignored".to_string(),
];
let opts = parse_opts(&args).unwrap().unwrap(); let opts = parse_opts(&args).unwrap().unwrap();
assert_eq!(opts.run_ignored, RunIgnored::Yes); assert_eq!(opts.run_ignored, RunIgnored::Yes);
} }

View File

@ -3510,6 +3510,7 @@ fn render_assoc_items(
"deref-methods-{:#}", "deref-methods-{:#}",
type_.print(cx.cache()) type_.print(cx.cache())
))); )));
debug!("Adding {} to deref id map", type_.print(cx.cache()));
cx.deref_id_map cx.deref_id_map
.borrow_mut() .borrow_mut()
.insert(type_.def_id_full(cx.cache()).unwrap(), id.clone()); .insert(type_.def_id_full(cx.cache()).unwrap(), id.clone());
@ -3626,6 +3627,7 @@ fn render_deref_methods(
_ => None, _ => None,
}) })
.expect("Expected associated type binding"); .expect("Expected associated type binding");
debug!("Render deref methods for {:#?}, target {:#?}", impl_.inner_impl().for_, target);
let what = let what =
AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut }; AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
if let Some(did) = target.def_id_full(cx.cache()) { if let Some(did) = target.def_id_full(cx.cache()) {
@ -4416,6 +4418,15 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
}) })
{ {
debug!("found target, real_target: {:?} {:?}", target, real_target); debug!("found target, real_target: {:?} {:?}", target, real_target);
if let Some(did) = target.def_id_full(cx.cache()) {
if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cx.cache()) {
// `impl Deref<Target = S> for S`
if did == type_did {
// Avoid infinite cycles
return;
}
}
}
let deref_mut = v let deref_mut = v
.iter() .iter()
.filter(|i| i.inner_impl().trait_.is_some()) .filter(|i| i.inner_impl().trait_.is_some())
@ -4464,13 +4475,6 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
.filter(|i| i.inner_impl().trait_.is_some()) .filter(|i| i.inner_impl().trait_.is_some())
.find(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == c.deref_trait_did) .find(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == c.deref_trait_did)
{ {
if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cx.cache()) {
// `impl Deref<Target = S> for S`
if target_did == type_did {
// Avoid infinite cycles
return;
}
}
sidebar_deref_methods(cx, out, target_deref_impl, target_impls); sidebar_deref_methods(cx, out, target_deref_impl, target_impls);
} }
} }

View File

@ -156,6 +156,7 @@ code, pre, a.test-arrow {
} }
.docblock pre code, .docblock-short pre code, .docblock code.spotlight { .docblock pre code, .docblock-short pre code, .docblock code.spotlight {
padding: 0; padding: 0;
padding-right: 1ex;
} }
.docblock code.spotlight :last-child { .docblock code.spotlight :last-child {
padding-bottom: 0.6em; padding-bottom: 0.6em;
@ -404,7 +405,7 @@ nav.sub {
text-overflow: ellipsis; text-overflow: ellipsis;
margin: 0; margin: 0;
} }
.docblock code, .docblock-short code { .docblock-short code {
white-space: pre-wrap; white-space: pre-wrap;
} }
@ -1624,6 +1625,10 @@ h4 > .notable-traits {
#settings-menu { #settings-menu {
top: 7px; top: 7px;
} }
.docblock {
margin-left: 12px;
}
} }
h3.notable { h3.notable {

View File

@ -0,0 +1,15 @@
// check-pass
// #81395: Fix ICE when recursing into Deref target only differing in type args
pub struct Generic<T>(T);
impl<'a> std::ops::Deref for Generic<&'a mut ()> {
type Target = Generic<&'a ()>;
fn deref(&self) -> &Self::Target {
unimplemented!()
}
}
impl<'a> Generic<&'a ()> {
pub fn some_method(&self) {}
}

View File

@ -1,6 +1,5 @@
// check-pass // check-pass
#![feature(array_value_iter)]
#![feature(trusted_len)] #![feature(trusted_len)]
use std::{ use std::{

View File

@ -1,6 +1,5 @@
// check-pass // check-pass
#![feature(array_value_iter)]
#![feature(trusted_len)] #![feature(trusted_len)]
use std::{ use std::{

View File

@ -122,7 +122,7 @@ LL | Point4( a , _ , _, _) => {}
| ^^^^^^ | ^^^^^^
help: use `..` to ignore the rest of the fields help: use `..` to ignore the rest of the fields
| |
LL | Point4( a , _ , ..) => {} LL | Point4( a, ..) => {}
| ^^^^ | ^^^^
error: aborting due to 8 previous errors error: aborting due to 8 previous errors

View File

@ -0,0 +1,23 @@
// force-host
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro_quote)]
extern crate proc_macro;
use proc_macro::{TokenStream, quote};
#[proc_macro_attribute]
pub fn first_attr(_: TokenStream, input: TokenStream) -> TokenStream {
let recollected: TokenStream = input.into_iter().collect();
quote! {
#[second_attr]
$recollected
}
}
#[proc_macro_attribute]
pub fn second_attr(_: TokenStream, input: TokenStream) -> TokenStream {
let _recollected: TokenStream = input.into_iter().collect();
TokenStream::new()
}

View File

@ -0,0 +1,17 @@
// check-pass
// aux-build:nonterminal-recollect-attr.rs
extern crate nonterminal_recollect_attr;
use nonterminal_recollect_attr::*;
macro_rules! my_macro {
($v:ident) => {
#[first_attr]
$v struct Foo {
field: u8
}
}
}
my_macro!(pub);
fn main() {}

View File

@ -10,15 +10,18 @@ const TEST2: _ = 42u32;
const TEST3: _ = Some(42); const TEST3: _ = Some(42);
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
trait Test4 { const TEST4: fn() -> _ = 42;
const TEST4: _ = 42; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
trait Test5 {
const TEST5: _ = 42;
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
} }
struct Test5; struct Test6;
impl Test5 { impl Test6 {
const TEST5: _ = 13; const TEST6: _ = 13;
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
} }

View File

@ -26,23 +26,32 @@ LL | const TEST3: _ = Some(42);
| help: replace `_` with the correct type: `Option<i32>` | help: replace `_` with the correct type: `Option<i32>`
error[E0121]: the type placeholder `_` is not allowed within types on item signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> $DIR/typeck_type_placeholder_item_help.rs:14:18 --> $DIR/typeck_type_placeholder_item_help.rs:13:22
| |
LL | const TEST4: _ = 42; LL | const TEST4: fn() -> _ = 42;
| ^
| |
| not allowed in type signatures
| help: use type parameters instead: `T`
error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> $DIR/typeck_type_placeholder_item_help.rs:17:18
|
LL | const TEST5: _ = 42;
| ^ | ^
| | | |
| not allowed in type signatures | not allowed in type signatures
| help: replace `_` with the correct type: `i32` | help: replace `_` with the correct type: `i32`
error[E0121]: the type placeholder `_` is not allowed within types on item signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> $DIR/typeck_type_placeholder_item_help.rs:21:18 --> $DIR/typeck_type_placeholder_item_help.rs:24:18
| |
LL | const TEST5: _ = 13; LL | const TEST6: _ = 13;
| ^ | ^
| | | |
| not allowed in type signatures | not allowed in type signatures
| help: replace `_` with the correct type: `i32` | help: replace `_` with the correct type: `i32`
error: aborting due to 5 previous errors error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0121`. For more information about this error, try `rustc --explain E0121`.