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/",
test(no_crate_inject, attr(deny(warnings)))
)]
#![feature(array_value_iter_slice)]
#![feature(dropck_eyepatch)]
#![feature(new_uninit)]
#![feature(maybe_uninit_slice)]
#![feature(array_value_iter)]
#![cfg_attr(bootstrap, feature(min_const_generics))]
#![feature(min_specialization)]
#![cfg_attr(test, feature(test))]

View File

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

View File

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

View File

@ -1254,15 +1254,7 @@ impl<'a> Parser<'a> {
f: impl FnOnce(&mut Self) -> PResult<'a, (R, TrailingToken)>,
) -> PResult<'a, R> {
let start_token = (self.token.clone(), self.token_spacing);
let cursor_snapshot = TokenCursor {
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 cursor_snapshot = self.token_cursor.clone();
let (mut ret, trailing_token) = f(self)?;

View File

@ -11,7 +11,6 @@
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(array_value_iter)]
#![feature(bool_to_option)]
#![feature(box_patterns)]
#![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.
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,
given a generic function `fn foo<T>(t: T)`: while checking the
type variable is an instance of a type parameter. That is,
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
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
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())],
Applicability::MachineApplicable,
);
} else if fields.len() > subpats.len() {
let after_fields_span = if pat_span == DUMMY_SP {
pat_span
} else {
pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi()
};
} else if fields.len() > subpats.len() && pat_span != DUMMY_SP {
let after_fields_span = pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi();
let all_fields_span = match subpats {
[] => after_fields_span,
[field] => field.span,
@ -1055,7 +1051,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Check if all the fields in the pattern are wildcards.
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(", ");
if !subpats.is_empty() {
wildcard_sugg = String::from(", ") + &wildcard_sugg;
@ -1080,7 +1088,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
} else {
err.span_suggestion_verbose(
after_fields_span,
tail_span,
"use `..` to ignore the rest of the fields",
String::from(", .."),
Applicability::MaybeIncorrect,

View File

@ -7,9 +7,9 @@ The type checker is responsible for:
1. Determining the type of each expression.
2. Resolving methods and traits.
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:
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
they are unknown. The actual checking of a function itself has
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
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/")]
#![feature(array_value_iter)]
#![feature(bool_to_option)]
#![feature(box_syntax)]
#![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")]
impl<T: fmt::Display + ?Sized, A: Allocator> fmt::Display for Box<T, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

View File

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

View File

@ -962,15 +962,13 @@ impl<T: ?Sized> Arc<T> {
/// # Examples
///
/// ```
/// #![feature(arc_mutate_strong_count)]
///
/// use std::sync::Arc;
///
/// let five = Arc::new(5);
///
/// unsafe {
/// 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
/// // the `Arc` between threads.
@ -979,8 +977,8 @@ impl<T: ?Sized> Arc<T> {
/// }
/// ```
#[inline]
#[unstable(feature = "arc_mutate_strong_count", issue = "71983")]
pub unsafe fn incr_strong_count(ptr: *const T) {
#[stable(feature = "arc_mutate_strong_count", since = "1.51.0")]
pub unsafe fn increment_strong_count(ptr: *const T) {
// Retain Arc, but don't touch refcount by wrapping in ManuallyDrop
let arc = unsafe { mem::ManuallyDrop::new(Arc::<T>::from_raw(ptr)) };
// Now increase refcount, but don't drop new refcount either
@ -1001,27 +999,25 @@ impl<T: ?Sized> Arc<T> {
/// # Examples
///
/// ```
/// #![feature(arc_mutate_strong_count)]
///
/// use std::sync::Arc;
///
/// let five = Arc::new(5);
///
/// unsafe {
/// 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
/// // the `Arc` between threads.
/// let five = Arc::from_raw(ptr);
/// assert_eq!(2, Arc::strong_count(&five));
/// Arc::decr_strong_count(ptr);
/// Arc::decrement_strong_count(ptr);
/// assert_eq!(1, Arc::strong_count(&five));
/// }
/// ```
#[inline]
#[unstable(feature = "arc_mutate_strong_count", issue = "71983")]
pub unsafe fn decr_strong_count(ptr: *const T) {
#[stable(feature = "arc_mutate_strong_count", since = "1.51.0")]
pub unsafe fn decrement_strong_count(ptr: *const T) {
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 {
// Increment the reference count of the arc to clone it.
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(
waker as *const (),
&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
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(

View File

@ -11,7 +11,7 @@ use crate::{
/// A by-value [array] iterator.
///
/// [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> {
/// 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> {
/// Creates a new iterator over the given `array`.
///
/// *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 = "65798")]
/// *Note*: this method might be deprecated in the future,
/// after [`IntoIterator` is implemented for arrays][array-into-iter].
///
/// # 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 {
// SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
// 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
/// yet.
#[unstable(feature = "array_value_iter_slice", issue = "65798")]
#[stable(feature = "array_value_iter", since = "1.51.0")]
pub fn as_slice(&self) -> &[T] {
// SAFETY: We know that all elements within `alive` are properly initialized.
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.
#[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] {
// SAFETY: We know that all elements within `alive` are properly initialized.
unsafe {

View File

@ -18,7 +18,7 @@ use crate::slice::{Iter, IterMut};
mod iter;
#[unstable(feature = "array_value_iter", issue = "65798")]
#[stable(feature = "array_value_iter", since = "1.51.0")]
pub use iter::IntoIter;
/// 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`,
/// 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
/// - transitive: `a == b` and `b == c` implies `a == c`.
/// - **Symmetric**: if `A: PartialEq<B>` and `B: PartialEq<A>`, then **`a == b`
/// implies `b == a`**; and
///
/// Note that these requirements mean that the trait itself must be implemented
/// symmetrically and transitively: if `T: PartialEq<U>` and `U: PartialEq<V>`
/// then `U: PartialEq<T>` and `T: PartialEq<V>`.
/// - **Transitive**: if `A: PartialEq<B>` and `B: PartialEq<C>` and `A:
/// PartialEq<C>`, then **`a == b` and `b == c` implies `a == c`**.
///
/// 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
///

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
////////////////////////////////////////////////////////////////////////////////

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
///
/// 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) {
const DIV: u64 = 1e19 as u64;
let high = (n >> 64) as u64;
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;
const FACTOR: u128 = 156927543384667019095894735580191660403;
for _ in 0..sr {
r = (r << 1) | (q >> 127);
q = (q << 1) | carry as u128;
let quot = if n < 1 << 83 {
((n >> 19) as u64 / (DIV >> 19)) as u128
} else {
u128_mulhi(n, FACTOR) >> 62
};
let s = (DIV as u128).wrapping_sub(r).wrapping_sub(1) as i128 >> 127;
carry = (s & 1) as u64;
r -= (DIV as u128) & s as u128;
}
((q << 1) | carry as u128, r as u64)
let rem = (n - quot * DIV as u128) as u64;
(quot, rem)
}
/// 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
/// from its underlying [`SourceIter`].
///
/// Calling [`next()`] guarantees that at least one value of the iterator's underlying source
/// 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.
/// Calling any method that advances the iterator, e.g. [`next()`] or [`try_fold()`],
/// guarantees that for each step at least one value of the iterator's underlying source
/// 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.
///
/// [`SourceIter`]: crate::iter::SourceIter
/// [`next()`]: Iterator::next
/// [`try_fold()`]: Iterator::try_fold
#[unstable(issue = "none", feature = "inplace_iteration")]
pub unsafe trait InPlaceIterable: Iterator {}

View File

@ -2852,13 +2852,12 @@ impl<T> [T] {
/// # Examples
///
/// ```
/// #![feature(slice_fill_with)]
///
/// let mut buf = vec![1; 10];
/// buf.fill_with(Default::default);
/// 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)
where
F: FnMut() -> T,

View File

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

View File

@ -110,10 +110,10 @@
//!
//! For Sets, all operations have the cost of the equivalent Map operation.
//!
//! | | get | insert | remove | predecessor | append |
//! |--------------|-----------|-----------|-----------|-------------|--------|
//! | [`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) |
//! | | get | insert | remove | range | append |
//! |--------------|-----------|-----------|-----------|-----------|--------|
//! | [`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) |
//!
//! # Correct and Efficient Usage of Collections
//!

View File

@ -4,7 +4,7 @@
mod tests;
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.
///
@ -58,6 +58,21 @@ impl BufRead for Empty {
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")]
impl fmt::Debug for Empty {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

View File

@ -1,5 +1,5 @@
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]
fn copy_copies() {
@ -29,6 +29,26 @@ fn empty_reads() {
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]
fn repeat_repeats() {
let mut r = repeat(4);

View File

@ -230,9 +230,9 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes {
// Unstable flags
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 include_ignored = unstable_optflag!(matches, allow_unstable, "include-ignored");
let time_options = get_time_options(&matches, allow_unstable)?;
let include_ignored = matches.opt_present("include-ignored");
let quiet = matches.opt_present("quiet");
let exact = matches.opt_present("exact");
let list = matches.opt_present("list");

View File

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

View File

@ -3510,6 +3510,7 @@ fn render_assoc_items(
"deref-methods-{:#}",
type_.print(cx.cache())
)));
debug!("Adding {} to deref id map", type_.print(cx.cache()));
cx.deref_id_map
.borrow_mut()
.insert(type_.def_id_full(cx.cache()).unwrap(), id.clone());
@ -3626,6 +3627,7 @@ fn render_deref_methods(
_ => None,
})
.expect("Expected associated type binding");
debug!("Render deref methods for {:#?}, target {:#?}", impl_.inner_impl().for_, target);
let what =
AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
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);
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
.iter()
.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())
.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);
}
}

View File

@ -156,6 +156,7 @@ code, pre, a.test-arrow {
}
.docblock pre code, .docblock-short pre code, .docblock code.spotlight {
padding: 0;
padding-right: 1ex;
}
.docblock code.spotlight :last-child {
padding-bottom: 0.6em;
@ -404,7 +405,7 @@ nav.sub {
text-overflow: ellipsis;
margin: 0;
}
.docblock code, .docblock-short code {
.docblock-short code {
white-space: pre-wrap;
}
@ -1624,6 +1625,10 @@ h4 > .notable-traits {
#settings-menu {
top: 7px;
}
.docblock {
margin-left: 12px;
}
}
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
#![feature(array_value_iter)]
#![feature(trusted_len)]
use std::{

View File

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

View File

@ -122,8 +122,8 @@ LL | Point4( a , _ , _, _) => {}
| ^^^^^^
help: use `..` to ignore the rest of the fields
|
LL | Point4( a , _ , ..) => {}
| ^^^^
LL | Point4( a, ..) => {}
| ^^^^
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);
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
trait Test4 {
const TEST4: _ = 42;
const TEST4: fn() -> _ = 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
}
struct Test5;
struct Test6;
impl Test5 {
const TEST5: _ = 13;
impl Test6 {
const TEST6: _ = 13;
//~^ 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>`
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
| help: replace `_` with the correct type: `i32`
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
| 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`.