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:
commit
7850c28a5f
@ -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))]
|
||||||
|
@ -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"]
|
||||||
|
@ -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)]
|
||||||
|
@ -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)?;
|
||||||
|
|
||||||
|
@ -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)]
|
||||||
|
@ -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).
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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)]
|
||||||
|
@ -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 {
|
||||||
|
@ -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)]
|
||||||
|
@ -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)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
@ -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 {
|
||||||
|
@ -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).
|
||||||
|
@ -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
|
||||||
///
|
///
|
||||||
|
@ -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
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -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. 61–72
|
||||||
|
///
|
||||||
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
|
||||||
}
|
}
|
||||||
|
@ -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 {}
|
||||||
|
@ -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,
|
||||||
|
@ -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)]
|
||||||
|
@ -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) |
|
||||||
//!
|
//!
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
15
src/test/rustdoc-ui/deref-generic.rs
Normal file
15
src/test/rustdoc-ui/deref-generic.rs
Normal 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) {}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
// check-pass
|
// check-pass
|
||||||
|
|
||||||
#![feature(array_value_iter)]
|
|
||||||
#![feature(trusted_len)]
|
#![feature(trusted_len)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// check-pass
|
// check-pass
|
||||||
|
|
||||||
#![feature(array_value_iter)]
|
|
||||||
#![feature(trusted_len)]
|
#![feature(trusted_len)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
}
|
17
src/test/ui/proc-macro/nonterminal-recollect-attr.rs
Normal file
17
src/test/ui/proc-macro/nonterminal-recollect-attr.rs
Normal 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() {}
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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`.
|
||||||
|
Loading…
Reference in New Issue
Block a user