Auto merge of #81018 - m-ou-se:rollup-7202dc7, r=m-ou-se

Rollup of 17 pull requests

Successful merges:

 - #79982 (Add missing methods to unix ExitStatusExt)
 - #80017 (Suggest `_` and `..` if a pattern has too few fields)
 - #80169 (Recommend panic::resume_unwind instead of panicking.)
 - #80217 (Add a `std::io::read_to_string` function)
 - #80444 (Add as_ref and as_mut methods for Bound)
 - #80567 (Add Iterator::intersperse_with)
 - #80829 (Get rid of `DepConstructor`)
 - #80895 (Fix handling of malicious Readers in read_to_end)
 - #80966 (Deprecate atomic::spin_loop_hint in favour of hint::spin_loop)
 - #80969 (Use better ICE message when no MIR is available)
 - #80972 (Remove unstable deprecated Vec::remove_item)
 - #80973 (Update books)
 - #80980 (Fixed incorrect doc comment)
 - #80981 (Fix -Cpasses=list and llvm version print with -vV)
 - #80985 (Fix stabilisation version of slice_strip)
 - #80990 (llvm: Remove the unused context from CreateDebugLocation)
 - #80991 (Fix formatting specifiers doc links)

Failed merges:

 - #80944 (Use Option::map_or instead of `.map(..).unwrap_or(..)`)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-01-14 20:21:20 +00:00
commit e38fb306b7
42 changed files with 802 additions and 167 deletions

View File

@ -552,7 +552,6 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
unsafe {
llvm::LLVMRustDIBuilderCreateDebugLocation(
utils::debug_context(self).llcontext,
line.unwrap_or(UNKNOWN_LINE_NUMBER),
col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
scope,

View File

@ -2102,7 +2102,6 @@ extern "C" {
);
pub fn LLVMRustDIBuilderCreateDebugLocation(
Context: &'a Context,
Line: c_uint,
Column: c_uint,
Scope: &'a DIScope,

View File

@ -798,7 +798,7 @@ pub fn version(binary: &str, matches: &getopts::Matches) {
println!("commit-date: {}", unw(util::commit_date_str()));
println!("host: {}", config::host_triple());
println!("release: {}", unw(util::release_str()));
if cfg!(llvm) {
if cfg!(feature = "llvm") {
get_builtin_codegen_backend("llvm")().print_version();
}
}
@ -1087,7 +1087,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
}
if cg_flags.iter().any(|x| *x == "passes=list") {
if cfg!(llvm) {
if cfg!(feature = "llvm") {
get_builtin_codegen_backend("llvm")().print_passes();
}
return None;

View File

@ -994,11 +994,9 @@ LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
}
extern "C" LLVMMetadataRef
LLVMRustDIBuilderCreateDebugLocation(LLVMContextRef ContextRef, unsigned Line,
unsigned Column, LLVMMetadataRef Scope,
LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
LLVMMetadataRef Scope,
LLVMMetadataRef InlinedAt) {
LLVMContext &Context = *unwrap(ContextRef);
DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(Scope),
unwrapDIPtr<MDNode>(InlinedAt));

View File

@ -29,9 +29,10 @@
//! contained no `DefId` for thing that had been removed.
//!
//! `DepNode` definition happens in the `define_dep_nodes!()` macro. This macro
//! defines the `DepKind` enum and a corresponding `dep_constructor` module. The
//! `dep_constructor` module links a `DepKind` to the parameters that are needed at
//! runtime in order to construct a valid `DepNode` fingerprint.
//! defines the `DepKind` enum. Each `DepKind` has its own parameters that are
//! needed at runtime in order to construct a valid `DepNode` fingerprint.
//! However, only `CompileCodegenUnit` is constructed explicitly (with
//! `make_compile_codegen_unit`).
//!
//! Because the macro sees what parameters a given `DepKind` requires, it can
//! "infer" some properties for each kind of `DepNode`:
@ -44,22 +45,14 @@
//! `DefId` it was computed from. In other cases, too much information gets
//! lost during fingerprint computation.
//!
//! The `dep_constructor` module, together with `DepNode::new()`, ensures that only
//! `make_compile_codegen_unit`, together with `DepNode::new()`, ensures that only
//! valid `DepNode` instances can be constructed. For example, the API does not
//! allow for constructing parameterless `DepNode`s with anything other
//! than a zeroed out fingerprint. More generally speaking, it relieves the
//! user of the `DepNode` API of having to know how to compute the expected
//! fingerprint for a given set of node parameters.
use crate::mir::interpret::{GlobalId, LitToConstInput};
use crate::traits;
use crate::traits::query::{
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
};
use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
use crate::ty::TyCtxt;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
@ -338,25 +331,6 @@ macro_rules! define_dep_nodes {
$($variant),*
}
#[allow(non_camel_case_types)]
pub mod dep_constructor {
use super::*;
$(
#[inline(always)]
#[allow(unreachable_code, non_snake_case)]
pub fn $variant(_tcx: TyCtxt<'_>, $(arg: $tuple_arg_ty)*) -> DepNode {
// tuple args
$({
erase!($tuple_arg_ty);
return DepNode::construct(_tcx, DepKind::$variant, &arg)
})*
return DepNode::construct(_tcx, DepKind::$variant, &())
}
)*
}
fn dep_kind_from_label_string(label: &str) -> Result<DepKind, ()> {
match label {
$(stringify!($variant) => Ok(DepKind::$variant),)*
@ -384,9 +358,16 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
[anon] TraitSelect,
// WARNING: if `Symbol` is changed, make sure you update `make_compile_codegen_unit` below.
[] CompileCodegenUnit(Symbol),
]);
// WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys.
// Be very careful changing this type signature!
crate fn make_compile_codegen_unit(tcx: TyCtxt<'_>, name: Symbol) -> DepNode {
DepNode::construct(tcx, DepKind::CompileCodegenUnit, &name)
}
pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>;
// We keep a lot of `DepNode`s in memory during compilation. It's not

View File

@ -13,7 +13,8 @@ pub use rustc_query_system::dep_graph::{
WorkProduct, WorkProductId,
};
pub use dep_node::{dep_constructor, label_strs, DepKind, DepNode, DepNodeExt};
crate use dep_node::make_compile_codegen_unit;
pub use dep_node::{label_strs, DepKind, DepNode, DepNodeExt};
pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepKind>;
pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps<DepKind>;

View File

@ -1,4 +1,4 @@
use crate::dep_graph::{dep_constructor, DepNode, WorkProduct, WorkProductId};
use crate::dep_graph::{DepNode, WorkProduct, WorkProductId};
use crate::ich::{NodeIdHashingMode, StableHashingContext};
use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt};
use rustc_attr::InlineAttr;
@ -362,7 +362,7 @@ impl<'tcx> CodegenUnit<'tcx> {
}
pub fn codegen_dep_node(&self, tcx: TyCtxt<'tcx>) -> DepNode {
dep_constructor::CompileCodegenUnit(tcx, self.name())
crate::dep_graph::make_compile_codegen_unit(tcx, self.name())
}
}

View File

@ -823,7 +823,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
}
if !tcx.is_mir_available(def_id) {
bug!("cannot create local mono-item for {:?}", def_id)
bug!("no MIR available for {:?}", def_id);
}
true

View File

@ -15,6 +15,7 @@ use rustc_span::hygiene::DesugaringKind;
use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::{Span, Spanned};
use rustc_span::symbol::Ident;
use rustc_span::{BytePos, DUMMY_SP};
use rustc_trait_selection::traits::{ObligationCause, Pattern};
use std::cmp;
@ -1001,7 +1002,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// More generally, the expected type wants a tuple variant with one field of an
// N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern
// with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`.
let missing_parenthesis = match (&expected.kind(), fields, had_err) {
let missing_parentheses = match (&expected.kind(), fields, had_err) {
// #67037: only do this if we could successfully type-check the expected type against
// the tuple struct pattern. Otherwise the substs could get out of range on e.g.,
// `let P() = U;` where `P != U` with `struct P<T>(T);`.
@ -1014,13 +1015,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
_ => false,
};
if missing_parenthesis {
if missing_parentheses {
let (left, right) = match subpats {
// This is the zero case; we aim to get the "hi" part of the `QPath`'s
// span as the "lo" and then the "hi" part of the pattern's span as the "hi".
// This looks like:
//
// help: missing parenthesis
// help: missing parentheses
// |
// L | let A(()) = A(());
// | ^ ^
@ -1029,17 +1030,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// last sub-pattern. In the case of `A(x)` the first and last may coincide.
// This looks like:
//
// help: missing parenthesis
// help: missing parentheses
// |
// L | let A((x, y)) = A((1, 2));
// | ^ ^
[first, ..] => (first.span.shrink_to_lo(), subpats.last().unwrap().span),
};
err.multipart_suggestion(
"missing parenthesis",
"missing parentheses",
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()
};
let all_fields_span = match subpats {
[] => after_fields_span,
[field] => field.span,
[first, .., last] => first.span.to(last.span),
};
// Check if all the fields in the pattern are wildcards.
let all_wildcards = subpats.iter().all(|pat| matches!(pat.kind, PatKind::Wild));
let mut wildcard_sugg = vec!["_"; fields.len() - subpats.len()].join(", ");
if !subpats.is_empty() {
wildcard_sugg = String::from(", ") + &wildcard_sugg;
}
err.span_suggestion_verbose(
after_fields_span,
"use `_` to explicitly ignore each field",
wildcard_sugg,
Applicability::MaybeIncorrect,
);
// Only suggest `..` if more than one field is missing
// or the pattern consists of all wildcards.
if fields.len() - subpats.len() > 1 || all_wildcards {
if subpats.is_empty() || all_wildcards {
err.span_suggestion_verbose(
all_fields_span,
"use `..` to ignore all fields",
String::from(".."),
Applicability::MaybeIncorrect,
);
} else {
err.span_suggestion_verbose(
after_fields_span,
"use `..` to ignore the rest of the fields",
String::from(", .."),
Applicability::MaybeIncorrect,
);
}
}
}
err.emit();

View File

@ -370,7 +370,7 @@ fn test_weak_count_locked() {
let n = Arc::weak_count(&a2);
assert!(n < 2, "bad weak count: {}", n);
#[cfg(miri)] // Miri's scheduler does not guarantee liveness, and thus needs this hint.
atomic::spin_loop_hint();
std::hint::spin_loop();
}
t.join().unwrap();
}

View File

@ -1953,27 +1953,6 @@ impl<T: PartialEq, A: Allocator> Vec<T, A> {
}
}
impl<T, A: Allocator> Vec<T, A> {
/// Removes the first instance of `item` from the vector if the item exists.
///
/// This method will be removed soon.
#[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")]
#[rustc_deprecated(
reason = "Removing the first item equal to a needle is already easily possible \
with iterators and the current Vec methods. Furthermore, having a method for \
one particular case of removal (linear search, only the first item, no swap remove) \
but not for others is inconsistent. This method will be removed soon.",
since = "1.46.0"
)]
pub fn remove_item<V>(&mut self, item: &V) -> Option<T>
where
T: PartialEq<V>,
{
let pos = self.iter().position(|x| *x == *item)?;
Some(self.remove(pos))
}
}
////////////////////////////////////////////////////////////////////////////////
// Internal methods and functions
////////////////////////////////////////////////////////////////////////////////

View File

@ -456,7 +456,9 @@ impl Display for Arguments<'_> {
///
/// When used with the alternate format specifier `#?`, the output is pretty-printed.
///
/// For more information on formatters, see [the module-level documentation][self].
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../../std/fmt/index.html
///
/// This trait can be used with `#[derive]` if all fields implement `Debug`. When
/// `derive`d for structs, it will use the name of the `struct`, then `{`, then a
@ -602,7 +604,9 @@ pub use macros::Debug;
/// `Display` is similar to [`Debug`], but `Display` is for user-facing
/// output, and so cannot be derived.
///
/// For more information on formatters, see [the module-level documentation][self].
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../../std/fmt/index.html
///
/// # Examples
///
@ -674,7 +678,9 @@ pub trait Display {
///
/// The alternate flag, `#`, adds a `0o` in front of the output.
///
/// For more information on formatters, see [the module-level documentation][self].
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../../std/fmt/index.html
///
/// # Examples
///
@ -726,7 +732,9 @@ pub trait Octal {
///
/// The alternate flag, `#`, adds a `0b` in front of the output.
///
/// For more information on formatters, see [the module-level documentation][self].
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../../std/fmt/index.html
///
/// # Examples
///
@ -782,7 +790,9 @@ pub trait Binary {
///
/// The alternate flag, `#`, adds a `0x` in front of the output.
///
/// For more information on formatters, see [the module-level documentation][self].
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../../std/fmt/index.html
///
/// # Examples
///
@ -835,7 +845,9 @@ pub trait LowerHex {
///
/// The alternate flag, `#`, adds a `0x` in front of the output.
///
/// For more information on formatters, see [the module-level documentation][self].
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../../std/fmt/index.html
///
/// # Examples
///
@ -883,7 +895,9 @@ pub trait UpperHex {
/// The `Pointer` trait should format its output as a memory location. This is commonly presented
/// as hexadecimal.
///
/// For more information on formatters, see [the module-level documentation][self].
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../../std/fmt/index.html
///
/// # Examples
///
@ -932,7 +946,9 @@ pub trait Pointer {
///
/// The `LowerExp` trait should format its output in scientific notation with a lower-case `e`.
///
/// For more information on formatters, see [the module-level documentation][self].
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../../std/fmt/index.html
///
/// # Examples
///
@ -981,7 +997,9 @@ pub trait LowerExp {
///
/// The `UpperExp` trait should format its output in scientific notation with an upper-case `E`.
///
/// For more information on formatters, see [the module-level documentation][self].
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../../std/fmt/index.html
///
/// # Examples
///
@ -1555,7 +1573,7 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
/// // We set alignment to the left with ">".
/// // We set alignment to the right with ">".
/// assert_eq!(&format!("{:G>3}", Foo), "GGG");
/// assert_eq!(&format!("{:t>6}", Foo), "tttttt");
/// ```

View File

@ -1,6 +1,9 @@
use super::Peekable;
/// An iterator adapter that places a separator between all elements.
///
/// This `struct` is created by [`Iterator::intersperse`]. See its documentation
/// for more information.
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
#[derive(Debug, Clone)]
pub struct Intersperse<I: Iterator>
@ -40,37 +43,146 @@ where
}
}
fn fold<B, F>(mut self, init: B, mut f: F) -> B
fn fold<B, F>(self, init: B, f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
let mut accum = init;
// Use `peek()` first to avoid calling `next()` on an empty iterator.
if !self.needs_sep || self.iter.peek().is_some() {
if let Some(x) = self.iter.next() {
accum = f(accum, x);
}
}
let element = &self.separator;
self.iter.fold(accum, |mut accum, x| {
accum = f(accum, element.clone());
accum = f(accum, x);
accum
})
let separator = self.separator;
intersperse_fold(self.iter, init, f, move || separator.clone(), self.needs_sep)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (lo, hi) = self.iter.size_hint();
let next_is_elem = !self.needs_sep;
let lo = lo.saturating_sub(next_is_elem as usize).saturating_add(lo);
let hi = match hi {
Some(hi) => hi.saturating_sub(next_is_elem as usize).checked_add(hi),
None => None,
};
(lo, hi)
intersperse_size_hint(&self.iter, self.needs_sep)
}
}
/// An iterator adapter that places a separator between all elements.
///
/// This `struct` is created by [`Iterator::intersperse_with`]. See its
/// documentation for more information.
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
pub struct IntersperseWith<I, G>
where
I: Iterator,
{
separator: G,
iter: Peekable<I>,
needs_sep: bool,
}
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
impl<I, G> crate::fmt::Debug for IntersperseWith<I, G>
where
I: Iterator + crate::fmt::Debug,
I::Item: crate::fmt::Debug,
G: crate::fmt::Debug,
{
fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
f.debug_struct("IntersperseWith")
.field("separator", &self.separator)
.field("iter", &self.iter)
.field("needs_sep", &self.needs_sep)
.finish()
}
}
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
impl<I, G> crate::clone::Clone for IntersperseWith<I, G>
where
I: Iterator + crate::clone::Clone,
I::Item: crate::clone::Clone,
G: Clone,
{
fn clone(&self) -> Self {
IntersperseWith {
separator: self.separator.clone(),
iter: self.iter.clone(),
needs_sep: self.needs_sep.clone(),
}
}
}
impl<I, G> IntersperseWith<I, G>
where
I: Iterator,
G: FnMut() -> I::Item,
{
pub(in crate::iter) fn new(iter: I, separator: G) -> Self {
Self { iter: iter.peekable(), separator, needs_sep: false }
}
}
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
impl<I, G> Iterator for IntersperseWith<I, G>
where
I: Iterator,
G: FnMut() -> I::Item,
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
if self.needs_sep && self.iter.peek().is_some() {
self.needs_sep = false;
Some((self.separator)())
} else {
self.needs_sep = true;
self.iter.next()
}
}
fn fold<B, F>(self, init: B, f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
intersperse_fold(self.iter, init, f, self.separator, self.needs_sep)
}
fn size_hint(&self) -> (usize, Option<usize>) {
intersperse_size_hint(&self.iter, self.needs_sep)
}
}
fn intersperse_size_hint<I>(iter: &I, needs_sep: bool) -> (usize, Option<usize>)
where
I: Iterator,
{
let (lo, hi) = iter.size_hint();
let next_is_elem = !needs_sep;
let lo = lo.saturating_sub(next_is_elem as usize).saturating_add(lo);
let hi = match hi {
Some(hi) => hi.saturating_sub(next_is_elem as usize).checked_add(hi),
None => None,
};
(lo, hi)
}
fn intersperse_fold<I, B, F, G>(
mut iter: Peekable<I>,
init: B,
mut f: F,
mut separator: G,
needs_sep: bool,
) -> B
where
I: Iterator,
F: FnMut(B, I::Item) -> B,
G: FnMut() -> I::Item,
{
let mut accum = init;
// Use `peek()` first to avoid calling `next()` on an empty iterator.
if !needs_sep || iter.peek().is_some() {
if let Some(x) = iter.next() {
accum = f(accum, x);
}
}
iter.fold(accum, |mut accum, x| {
accum = f(accum, separator());
accum = f(accum, x);
accum
})
}

View File

@ -43,7 +43,7 @@ pub use self::flatten::Flatten;
pub use self::copied::Copied;
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
pub use self::intersperse::Intersperse;
pub use self::intersperse::{Intersperse, IntersperseWith};
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
pub use self::map_while::MapWhile;

View File

@ -395,8 +395,6 @@ pub use self::adapters::Cloned;
pub use self::adapters::Copied;
#[stable(feature = "iterator_flatten", since = "1.29.0")]
pub use self::adapters::Flatten;
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
pub use self::adapters::Intersperse;
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
pub use self::adapters::MapWhile;
#[unstable(feature = "inplace_iteration", issue = "none")]
@ -410,6 +408,8 @@ pub use self::adapters::{
Chain, Cycle, Enumerate, Filter, FilterMap, FlatMap, Fuse, Inspect, Map, Peekable, Rev, Scan,
Skip, SkipWhile, Take, TakeWhile, Zip,
};
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
pub use self::adapters::{Intersperse, IntersperseWith};
pub(crate) use self::adapters::process_results;

View File

@ -8,7 +8,7 @@ use crate::ops::{Add, ControlFlow, Try};
use super::super::TrustedRandomAccess;
use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
use super::super::{FlatMap, Flatten};
use super::super::{FromIterator, Intersperse, Product, Sum, Zip};
use super::super::{FromIterator, Intersperse, IntersperseWith, Product, Sum, Zip};
use super::super::{
Inspect, Map, MapWhile, Peekable, Rev, Scan, Skip, SkipWhile, StepBy, Take, TakeWhile,
};
@ -571,6 +571,9 @@ pub trait Iterator {
/// Places a copy of `separator` between all elements.
///
/// In case the separator does not implement [`Clone`] or needs to be
/// computed every time, use [`intersperse_with`].
///
/// # Examples
///
/// Basic usage:
@ -578,9 +581,12 @@ pub trait Iterator {
/// ```
/// #![feature(iter_intersperse)]
///
/// let hello = ["Hello", "World"].iter().copied().intersperse(" ").collect::<String>();
/// assert_eq!(hello, "Hello World");
/// let hello = ["Hello", "World", "!"].iter().copied().intersperse(" ").collect::<String>();
/// assert_eq!(hello, "Hello World !");
/// ```
///
/// [`Clone`]: crate::clone::Clone
/// [`intersperse_with`]: Iterator::intersperse_with
#[inline]
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
@ -591,6 +597,33 @@ pub trait Iterator {
Intersperse::new(self, separator)
}
/// Places an element generated by `separator` between all elements.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(iter_intersperse)]
///
/// let src = ["Hello", "to", "all", "people", "!!"].iter().copied();
///
/// let mut happy_emojis = [" ❤️ ", " 😀 "].iter().copied();
/// let separator = || happy_emojis.next().unwrap_or(" 🦀 ");
///
/// let result = src.intersperse_with(separator).collect::<String>();
/// assert_eq!(result, "Hello ❤️ to 😀 all 🦀 people 🦀 !!");
/// ```
#[inline]
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
where
Self: Sized,
G: FnMut() -> Self::Item,
{
IntersperseWith::new(self, separator)
}
/// Takes a closure and creates an iterator which calls that closure on each
/// element.
///

View File

@ -401,7 +401,7 @@ macro_rules! write {
/// For more information, see [`write!`]. For information on the format string syntax, see
/// [`std::fmt`].
///
/// [`std::fmt`]: crate::fmt
/// [`std::fmt`]: ../std/fmt/index.html
///
/// # Examples
///
@ -730,7 +730,7 @@ pub(crate) mod builtin {
/// [`Display`]: crate::fmt::Display
/// [`Debug`]: crate::fmt::Debug
/// [`fmt::Arguments`]: crate::fmt::Arguments
/// [`std::fmt`]: crate::fmt
/// [`std::fmt`]: ../std/fmt/index.html
/// [`format!`]: ../std/macro.format.html
/// [`println!`]: ../std/macro.println.html
///
@ -1194,7 +1194,7 @@ pub(crate) mod builtin {
/// be provided with or without arguments for formatting. See [`std::fmt`]
/// for syntax for this form.
///
/// [`std::fmt`]: crate::fmt
/// [`std::fmt`]: ../std/fmt/index.html
///
/// # Examples
///

View File

@ -678,6 +678,29 @@ pub enum Bound<T> {
Unbounded,
}
#[unstable(feature = "bound_as_ref", issue = "80996")]
impl<T> Bound<T> {
/// Converts from `&Bound<T>` to `Bound<&T>`.
#[inline]
pub fn as_ref(&self) -> Bound<&T> {
match *self {
Included(ref x) => Included(x),
Excluded(ref x) => Excluded(x),
Unbounded => Unbounded,
}
}
/// Converts from `&mut Bound<T>` to `Bound<&T>`.
#[inline]
pub fn as_mut(&mut self) -> Bound<&mut T> {
match *self {
Included(ref mut x) => Included(x),
Excluded(ref mut x) => Excluded(x),
Unbounded => Unbounded,
}
}
}
impl<T: Clone> Bound<&T> {
/// Map a `Bound<&T>` to a `Bound<T>` by cloning the contents of the bound.
///

View File

@ -1877,7 +1877,7 @@ impl<T> [T] {
/// Some(b"llo".as_ref()));
/// ```
#[must_use = "returns the subslice without modifying the original"]
#[stable(feature = "slice_strip", since = "1.50.0")]
#[stable(feature = "slice_strip", since = "1.51.0")]
pub fn strip_prefix<P: SlicePattern<Item = T> + ?Sized>(&self, prefix: &P) -> Option<&[T]>
where
T: PartialEq,
@ -1911,7 +1911,7 @@ impl<T> [T] {
/// assert_eq!(v.strip_suffix(&[50, 30]), None);
/// ```
#[must_use = "returns the subslice without modifying the original"]
#[stable(feature = "slice_strip", since = "1.50.0")]
#[stable(feature = "slice_strip", since = "1.51.0")]
pub fn strip_suffix<P: SlicePattern<Item = T> + ?Sized>(&self, suffix: &P) -> Option<&[T]>
where
T: PartialEq,
@ -3323,7 +3323,7 @@ pub trait SlicePattern {
fn as_slice(&self) -> &[Self::Item];
}
#[stable(feature = "slice_strip", since = "1.50.0")]
#[stable(feature = "slice_strip", since = "1.51.0")]
impl<T> SlicePattern for [T] {
type Item = T;
@ -3333,7 +3333,7 @@ impl<T> SlicePattern for [T] {
}
}
#[stable(feature = "slice_strip", since = "1.50.0")]
#[stable(feature = "slice_strip", since = "1.51.0")]
impl<T, const N: usize> SlicePattern for [T; N] {
type Item = T;

View File

@ -120,21 +120,6 @@ use crate::intrinsics;
use crate::hint::spin_loop;
/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock").
///
/// This function is expected to be deprecated in favor of
/// [`hint::spin_loop`].
///
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
/// do anything at all.
///
/// [`hint::spin_loop`]: crate::hint::spin_loop
#[inline]
#[stable(feature = "spin_loop_hint", since = "1.24.0")]
pub fn spin_loop_hint() {
spin_loop()
}
/// A boolean type which can be safely shared between threads.
///
/// This type has the same in-memory representation as a [`bool`].
@ -2791,3 +2776,15 @@ impl<T> fmt::Pointer for AtomicPtr<T> {
fmt::Pointer::fmt(&self.load(Ordering::SeqCst), f)
}
}
/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock").
///
/// This function is deprecated in favor of [`hint::spin_loop`].
///
/// [`hint::spin_loop`]: crate::hint::spin_loop
#[inline]
#[stable(feature = "spin_loop_hint", since = "1.24.0")]
#[rustc_deprecated(since = "1.51.0", reason = "use hint::spin_loop instead")]
pub fn spin_loop_hint() {
spin_loop()
}

View File

@ -3508,6 +3508,12 @@ pub fn extend_for_unit() {
#[test]
fn test_intersperse() {
let v = std::iter::empty().intersperse(0u32).collect::<Vec<_>>();
assert_eq!(v, vec![]);
let v = std::iter::once(1).intersperse(0).collect::<Vec<_>>();
assert_eq!(v, vec![1]);
let xs = ["a", "", "b", "c"];
let v: Vec<&str> = xs.iter().map(|x| x.clone()).intersperse(", ").collect();
let text: String = v.concat();
@ -3520,6 +3526,9 @@ fn test_intersperse() {
#[test]
fn test_intersperse_size_hint() {
let iter = std::iter::empty::<i32>().intersperse(0);
assert_eq!(iter.size_hint(), (0, Some(0)));
let xs = ["a", "", "b", "c"];
let mut iter = xs.iter().map(|x| x.clone()).intersperse(", ");
assert_eq!(iter.size_hint(), (7, Some(7)));
@ -3587,3 +3596,24 @@ fn test_try_fold_specialization_intersperse_err() {
iter.try_for_each(|item| if item == "b" { None } else { Some(()) });
assert_eq!(iter.next(), None);
}
#[test]
fn test_intersperse_with() {
#[derive(PartialEq, Debug)]
struct NotClone {
u: u32,
}
let r = vec![NotClone { u: 0 }, NotClone { u: 1 }]
.into_iter()
.intersperse_with(|| NotClone { u: 2 })
.collect::<Vec<_>>();
assert_eq!(r, vec![NotClone { u: 0 }, NotClone { u: 2 }, NotClone { u: 1 }]);
let mut ctr = 100;
let separator = || {
ctr *= 2;
ctr
};
let r = (0..3).intersperse_with(separator).collect::<Vec<_>>();
assert_eq!(r, vec![0, 200, 1, 400, 2]);
}

View File

@ -366,7 +366,6 @@ where
{
let start_len = buf.len();
let mut g = Guard { len: buf.len(), buf };
let ret;
loop {
if g.len == g.buf.len() {
unsafe {
@ -385,21 +384,20 @@ where
}
}
match r.read(&mut g.buf[g.len..]) {
Ok(0) => {
ret = Ok(g.len - start_len);
break;
let buf = &mut g.buf[g.len..];
match r.read(buf) {
Ok(0) => return Ok(g.len - start_len),
Ok(n) => {
// We can't allow bogus values from read. If it is too large, the returned vec could have its length
// set past its capacity, or if it overflows the vec could be shortened which could create an invalid
// string if this is called via read_to_string.
assert!(n <= buf.len());
g.len += n;
}
Ok(n) => g.len += n,
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => {
ret = Err(e);
break;
}
Err(e) => return Err(e),
}
}
ret
}
pub(crate) fn default_read_vectored<F>(read: F, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
@ -944,6 +942,54 @@ pub trait Read {
}
}
/// Read all bytes from a [reader][Read] into a new [`String`].
///
/// This is a convenience function for [`Read::read_to_string`]. Using this
/// function avoids having to create a variable first and provides more type
/// safety since you can only get the buffer out if there were no errors. (If you
/// use [`Read::read_to_string`] you have to remember to check whether the read
/// succeeded because otherwise your buffer will be empty or only partially full.)
///
/// # Performance
///
/// The downside of this function's increased ease of use and type safety is
/// that it gives you less control over performance. For example, you can't
/// pre-allocate memory like you can using [`String::with_capacity`] and
/// [`Read::read_to_string`]. Also, you can't re-use the buffer if an error
/// occurs while reading.
///
/// In many cases, this function's performance will be adequate and the ease of use
/// and type safety tradeoffs will be worth it. However, there are cases where you
/// need more control over performance, and in those cases you should definitely use
/// [`Read::read_to_string`] directly.
///
/// # Errors
///
/// This function forces you to handle errors because the output (the `String`)
/// is wrapped in a [`Result`]. See [`Read::read_to_string`] for the errors
/// that can occur. If any error occurs, you will get an [`Err`], so you
/// don't have to worry about your buffer being empty or partially full.
///
/// # Examples
///
/// ```no_run
/// #![feature(io_read_to_string)]
///
/// # use std::io;
/// fn main() -> io::Result<()> {
/// let stdin = io::read_to_string(&mut io::stdin())?;
/// println!("Stdin was:");
/// println!("{}", stdin);
/// Ok(())
/// }
/// ```
#[unstable(feature = "io_read_to_string", issue = "80218")]
pub fn read_to_string<R: Read>(reader: &mut R) -> Result<String> {
let mut buf = String::new();
reader.read_to_string(&mut buf)?;
Ok(buf)
}
/// A buffer type used with `Read::read_vectored`.
///
/// It is semantically a wrapper around an `&mut [u8]`, but is guaranteed to be

View File

@ -1,9 +1,10 @@
use crate::cell::UnsafeCell;
use crate::collections::VecDeque;
use crate::ffi::c_void;
use crate::hint;
use crate::ops::{Deref, DerefMut, Drop};
use crate::ptr;
use crate::sync::atomic::{spin_loop_hint, AtomicUsize, Ordering};
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::hermit::abi;
/// This type provides a lock based on busy waiting to realize mutual exclusion
@ -46,7 +47,7 @@ impl<T> Spinlock<T> {
fn obtain_lock(&self) {
let ticket = self.queue.fetch_add(1, Ordering::SeqCst) + 1;
while self.dequeue.load(Ordering::SeqCst) != ticket {
spin_loop_hint();
hint::spin_loop();
}
}

View File

@ -2,8 +2,9 @@
mod tests;
use crate::cell::UnsafeCell;
use crate::hint;
use crate::ops::{Deref, DerefMut};
use crate::sync::atomic::{spin_loop_hint, AtomicBool, Ordering};
use crate::sync::atomic::{AtomicBool, Ordering};
#[derive(Default)]
pub struct SpinMutex<T> {
@ -32,7 +33,7 @@ impl<T> SpinMutex<T> {
match self.try_lock() {
None => {
while self.lock.load(Ordering::Relaxed) {
spin_loop_hint()
hint::spin_loop()
}
}
Some(guard) => return guard,

View File

@ -9,6 +9,14 @@ use crate::process;
use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
mod private {
/// This trait being unreachable from outside the crate
/// prevents other implementations of the `ExitStatusExt` trait,
/// which allows potentially adding more trait methods in the future.
#[stable(feature = "none", since = "1.51.0")]
pub trait Sealed {}
}
/// Unix-specific extensions to the [`process::Command`] builder.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait CommandExt {
@ -163,18 +171,48 @@ impl CommandExt for process::Command {
}
/// Unix-specific extensions to [`process::ExitStatus`].
///
/// This trait is sealed: it cannot be implemented outside the standard library.
/// This is so that future additional methods are not breaking changes.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ExitStatusExt {
pub trait ExitStatusExt: private::Sealed {
/// Creates a new `ExitStatus` from the raw underlying `i32` return value of
/// a process.
#[stable(feature = "exit_status_from", since = "1.12.0")]
fn from_raw(raw: i32) -> Self;
/// If the process was terminated by a signal, returns that signal.
///
/// In other words, if `WIFSIGNALED`, this returns `WTERMSIG`.
#[stable(feature = "rust1", since = "1.0.0")]
fn signal(&self) -> Option<i32>;
/// If the process was terminated by a signal, says whether it dumped core.
#[unstable(feature = "unix_process_wait_more", issue = "80695")]
fn core_dumped(&self) -> bool;
/// If the process was stopped by a signal, returns that signal.
///
/// In other words, if `WIFSTOPPED`, this returns `WSTOPSIG`. This is only possible if the status came from
/// a `wait` system call which was passed `WUNTRACED`, was then converted into an `ExitStatus`.
#[unstable(feature = "unix_process_wait_more", issue = "80695")]
fn stopped_signal(&self) -> Option<i32>;
/// Whether the process was continued from a stopped status.
///
/// Ie, `WIFCONTINUED`. This is only possible if the status came from a `wait` system call
/// which was passed `WCONTINUED`, was then converted into an `ExitStatus`.
#[unstable(feature = "unix_process_wait_more", issue = "80695")]
fn continued(&self) -> bool;
/// Returns the underlying raw `wait` status.
#[unstable(feature = "unix_process_wait_more", issue = "80695")]
fn into_raw(self) -> i32;
}
#[stable(feature = "none", since = "1.51.0")]
impl private::Sealed for process::ExitStatus {}
#[stable(feature = "rust1", since = "1.0.0")]
impl ExitStatusExt for process::ExitStatus {
fn from_raw(raw: i32) -> Self {
@ -184,6 +222,22 @@ impl ExitStatusExt for process::ExitStatus {
fn signal(&self) -> Option<i32> {
self.as_inner().signal()
}
fn core_dumped(&self) -> bool {
self.as_inner().core_dumped()
}
fn stopped_signal(&self) -> Option<i32> {
self.as_inner().stopped_signal()
}
fn continued(&self) -> bool {
self.as_inner().continued()
}
fn into_raw(self) -> i32 {
self.as_inner().into_raw().into()
}
}
#[stable(feature = "process_extensions", since = "1.2.0")]

View File

@ -245,6 +245,50 @@ impl ExitStatus {
pub fn signal(&self) -> Option<i32> {
None
}
// FIXME: The actually-Unix implementation in process_unix.rs uses WSTOPSIG, WCOREDUMP et al.
// I infer from the implementation of `success`, `code` and `signal` above that these are not
// available on Fuchsia.
//
// It does not appear that Fuchsia is Unix-like enough to implement ExitStatus (or indeed many
// other things from std::os::unix) properly. This veneer is always going to be a bodge. So
// while I don't know if these implementations are actually correct, I think they will do for
// now at least.
pub fn core_dumped(&self) -> bool {
false
}
pub fn stopped_signal(&self) -> Option<i32> {
None
}
pub fn continued(&self) -> bool {
false
}
pub fn into_raw(&self) -> c_int {
// We don't know what someone who calls into_raw() will do with this value, but it should
// have the conventional Unix representation. Despite the fact that this is not
// standardised in SuS or POSIX, all Unix systems encode the signal and exit status the
// same way. (Ie the WIFEXITED, WEXITSTATUS etc. macros have identical behaviour on every
// Unix.)
//
// The caller of `std::os::unix::into_raw` is probably wanting a Unix exit status, and may
// do their own shifting and masking, or even pass the status to another computer running a
// different Unix variant.
//
// The other view would be to say that the caller on Fuchsia ought to know that `into_raw`
// will give a raw Fuchsia status (whatever that is - I don't know, personally). That is
// not possible here becaause we must return a c_int because that's what Unix (including
// SuS and POSIX) say a wait status is, but Fuchsia apparently uses a u64, so it won't
// necessarily fit.
//
// It seems to me that that the right answer would be to provide std::os::fuchsia with its
// own ExitStatusExt, rather that trying to provide a not very convincing imitation of
// Unix. Ie, std::os::unix::process:ExitStatusExt ought not to exist on Fuchsia. But
// fixing this up that is beyond the scope of my efforts now.
let exit_status_as_if_unix: u8 = self.0.try_into().expect("Fuchsia process return code bigger than 8 bits, but std::os::unix::ExitStatusExt::into_raw() was called to try to convert the value into a traditional Unix-style wait status, which cannot represent values greater than 255.");
let wait_status_as_if_unix = (exit_status_as_if_unix as c_int) << 8;
wait_status_as_if_unix
}
}
/// Converts a raw `c_int` to a type-safe `ExitStatus` by wrapping it without copying.

View File

@ -479,7 +479,23 @@ impl ExitStatus {
}
pub fn signal(&self) -> Option<i32> {
if !self.exited() { Some(libc::WTERMSIG(self.0)) } else { None }
if libc::WIFSIGNALED(self.0) { Some(libc::WTERMSIG(self.0)) } else { None }
}
pub fn core_dumped(&self) -> bool {
libc::WIFSIGNALED(self.0) && libc::WCOREDUMP(self.0)
}
pub fn stopped_signal(&self) -> Option<i32> {
if libc::WIFSTOPPED(self.0) { Some(libc::WSTOPSIG(self.0)) } else { None }
}
pub fn continued(&self) -> bool {
libc::WIFCONTINUED(self.0)
}
pub fn into_raw(&self) -> c_int {
self.0
}
}

View File

@ -7,6 +7,14 @@ use crate::process;
use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
mod private {
/// This trait being unreachable from outside the crate
/// prevents other implementations of the `ExitStatusExt` trait,
/// which allows potentially adding more trait methods in the future.
#[stable(feature = "none", since = "1.51.0")]
pub trait Sealed {}
}
#[stable(feature = "process_extensions", since = "1.2.0")]
impl FromRawHandle for process::Stdio {
unsafe fn from_raw_handle(handle: RawHandle) -> process::Stdio {
@ -73,8 +81,11 @@ impl IntoRawHandle for process::ChildStderr {
}
/// Windows-specific extensions to [`process::ExitStatus`].
///
/// This trait is sealed: it cannot be implemented outside the standard library.
/// This is so that future additional methods are not breaking changes.
#[stable(feature = "exit_status_from", since = "1.12.0")]
pub trait ExitStatusExt {
pub trait ExitStatusExt: private::Sealed {
/// Creates a new `ExitStatus` from the raw underlying `u32` return value of
/// a process.
#[stable(feature = "exit_status_from", since = "1.12.0")]
@ -88,6 +99,9 @@ impl ExitStatusExt for process::ExitStatus {
}
}
#[stable(feature = "none", since = "1.51.0")]
impl private::Sealed for process::ExitStatus {}
/// Windows-specific extensions to the [`process::Command`] builder.
#[stable(feature = "windows_process_extensions", since = "1.16.0")]
pub trait CommandExt {

View File

@ -1186,32 +1186,37 @@ impl fmt::Debug for Thread {
/// the [`Error`](crate::error::Error) trait.
///
/// Thus, a sensible way to handle a thread panic is to either:
/// 1. `unwrap` the `Result<T>`, propagating the panic
///
/// 1. propagate the panic with [`std::panic::resume_unwind`]
/// 2. or in case the thread is intended to be a subsystem boundary
/// that is supposed to isolate system-level failures,
/// match on the `Err` variant and handle the panic in an appropriate way.
/// match on the `Err` variant and handle the panic in an appropriate way
///
/// A thread that completes without panicking is considered to exit successfully.
///
/// # Examples
///
/// Matching on the result of a joined thread:
///
/// ```no_run
/// use std::thread;
/// use std::fs;
/// use std::{fs, thread, panic};
///
/// fn copy_in_thread() -> thread::Result<()> {
/// thread::spawn(move || { fs::copy("foo.txt", "bar.txt").unwrap(); }).join()
/// thread::spawn(|| {
/// fs::copy("foo.txt", "bar.txt").unwrap();
/// }).join()
/// }
///
/// fn main() {
/// match copy_in_thread() {
/// Ok(_) => println!("this is fine"),
/// Err(_) => println!("thread panicked"),
/// Ok(_) => println!("copy succeeded"),
/// Err(e) => panic::resume_unwind(e),
/// }
/// }
/// ```
///
/// [`Result`]: crate::result::Result
/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind
#[stable(feature = "rust1", since = "1.0.0")]
pub type Result<T> = crate::result::Result<T, Box<dyn Any + Send + 'static>>;

@ -1 +1 @@
Subproject commit 5bb44f8b5b0aa105c8b22602e9b18800484afa21
Subproject commit ac57a0ddd23d173b26731ccf939f3ba729753275

@ -1 +1 @@
Subproject commit ba34b8a968f9531d38c4dc4411d5568b7c076bfe
Subproject commit ceec19e873be87c6ee5666b030c6bb612f889a96

@ -1 +1 @@
Subproject commit a5a48441d411f61556b57d762b03d6874afe575d
Subproject commit a8584998eacdea7106a1dfafcbf6c1c06fcdf925

@ -1 +1 @@
Subproject commit b278478b766178491a8b6f67afa4bcd6b64d977a
Subproject commit 50af691f838937c300b47812d0507c6d88c14f97

@ -1 +1 @@
Subproject commit 1cce0737d6a7d3ceafb139b4a206861fb1dcb2ab
Subproject commit 03e23af01f0b4f83a3a513da280e1ca92587f2ec

View File

@ -31,6 +31,15 @@ LL | struct TupleStruct<S, T>(S, T);
...
LL | TupleStruct(_) = TupleStruct(1, 2);
| ^^^^^^^^^^^^^^ expected 2 fields, found 1
|
help: use `_` to explicitly ignore each field
|
LL | TupleStruct(_, _) = TupleStruct(1, 2);
| ^^^
help: use `..` to ignore all fields
|
LL | TupleStruct(..) = TupleStruct(1, 2);
| ^^
error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
--> $DIR/tuple_struct_destructure_fail.rs:34:5
@ -49,6 +58,15 @@ LL | SingleVariant(S, T)
...
LL | Enum::SingleVariant(_) = Enum::SingleVariant(1, 2);
| ^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 1
|
help: use `_` to explicitly ignore each field
|
LL | Enum::SingleVariant(_, _) = Enum::SingleVariant(1, 2);
| ^^^
help: use `..` to ignore all fields
|
LL | Enum::SingleVariant(..) = Enum::SingleVariant(1, 2);
| ^^
error[E0070]: invalid left-hand side of assignment
--> $DIR/tuple_struct_destructure_fail.rs:40:12

View File

@ -6,6 +6,11 @@ LL | Apple(String, String),
...
LL | Fruit::Apple(a) => {},
| ^^^^^^^^^^^^^^^ expected 2 fields, found 1
|
help: use `_` to explicitly ignore each field
|
LL | Fruit::Apple(a, _) => {},
| ^^^
error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
--> $DIR/E0023.rs:12:9
@ -34,7 +39,7 @@ LL | Orange((String, String)),
LL | Fruit::Orange(a, b) => {},
| ^^^^^^^^^^^^^^^^^^^ expected 1 field, found 2
|
help: missing parenthesis
help: missing parentheses
|
LL | Fruit::Orange((a, b)) => {},
| ^ ^
@ -48,7 +53,7 @@ LL | Banana(()),
LL | Fruit::Banana() => {},
| ^^^^^^^^^^^^^^^ expected 1 field, found 0
|
help: missing parenthesis
help: missing parentheses
|
LL | Fruit::Banana(()) => {},
| ^ ^

View File

@ -17,6 +17,15 @@ LL | struct P<T>(T); // 1 type parameter wanted
...
LL | let P() = U {};
| ^^^ expected 1 field, found 0
|
help: use `_` to explicitly ignore each field
|
LL | let P(_) = U {};
| ^
help: use `..` to ignore all fields
|
LL | let P(..) = U {};
| ^^
error: aborting due to 2 previous errors

View File

@ -26,6 +26,11 @@ LL | struct Binder(i32, i32, i32);
...
LL | Binder(_a, _x @ ..) => {}
| ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 2
|
help: use `_` to explicitly ignore each field
|
LL | Binder(_a, _x @ .., _) => {}
| ^^^
error: aborting due to 3 previous errors

View File

@ -6,6 +6,15 @@ LL | Rgb(usize, usize, usize),
...
LL | Color::Rgb(_, _) => { }
| ^^^^^^^^^^^^^^^^ expected 3 fields, found 2
|
help: use `_` to explicitly ignore each field
|
LL | Color::Rgb(_, _, _) => { }
| ^^^
help: use `..` to ignore all fields
|
LL | Color::Rgb(..) => { }
| ^^
error: aborting due to previous error

View File

@ -26,6 +26,11 @@ LL | A(u8, u8),
...
LL | E::A(x @ ..) => {
| ^^^^^^^^^^^^ expected 2 fields, found 1
|
help: use `_` to explicitly ignore each field
|
LL | E::A(x @ .., _) => {
| ^^^
error: aborting due to 3 previous errors

View File

@ -0,0 +1,55 @@
struct S(i32, f32);
enum E {
S(i32, f32),
}
struct Point4(i32, i32, i32, i32);
fn main() {
match S(0, 1.0) {
S(x) => {}
//~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields
//~| HELP use `_` to explicitly ignore each field
}
match S(0, 1.0) {
S(_) => {}
//~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields
//~| HELP use `_` to explicitly ignore each field
//~| HELP use `..` to ignore all fields
}
match S(0, 1.0) {
S() => {}
//~^ ERROR this pattern has 0 fields, but the corresponding tuple struct has 2 fields
//~| HELP use `_` to explicitly ignore each field
//~| HELP use `..` to ignore all fields
}
match E::S(0, 1.0) {
E::S(x) => {}
//~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields
//~| HELP use `_` to explicitly ignore each field
}
match E::S(0, 1.0) {
E::S(_) => {}
//~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields
//~| HELP use `_` to explicitly ignore each field
//~| HELP use `..` to ignore all fields
}
match E::S(0, 1.0) {
E::S() => {}
//~^ ERROR this pattern has 0 fields, but the corresponding tuple variant has 2 fields
//~| HELP use `_` to explicitly ignore each field
//~| HELP use `..` to ignore all fields
}
match E::S(0, 1.0) {
E::S => {}
//~^ ERROR expected unit struct, unit variant or constant, found tuple variant `E::S`
//~| HELP use the tuple variant pattern syntax instead
}
match Point4(0, 1, 2, 3) {
Point4( a , _ ) => {}
//~^ ERROR this pattern has 2 fields, but the corresponding tuple struct has 4 fields
//~| HELP use `_` to explicitly ignore each field
//~| HELP use `..` to ignore the rest of the fields
}
}

View File

@ -0,0 +1,131 @@
error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::S`
--> $DIR/pat-tuple-underfield.rs:44:9
|
LL | S(i32, f32),
| ----------- `E::S` defined here
...
LL | E::S => {}
| ^^^^ help: use the tuple variant pattern syntax instead: `E::S(_, _)`
error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields
--> $DIR/pat-tuple-underfield.rs:9:9
|
LL | struct S(i32, f32);
| ------------------- tuple struct defined here
...
LL | S(x) => {}
| ^^^^ expected 2 fields, found 1
|
help: use `_` to explicitly ignore each field
|
LL | S(x, _) => {}
| ^^^
error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields
--> $DIR/pat-tuple-underfield.rs:14:9
|
LL | struct S(i32, f32);
| ------------------- tuple struct defined here
...
LL | S(_) => {}
| ^^^^ expected 2 fields, found 1
|
help: use `_` to explicitly ignore each field
|
LL | S(_, _) => {}
| ^^^
help: use `..` to ignore all fields
|
LL | S(..) => {}
| ^^
error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields
--> $DIR/pat-tuple-underfield.rs:20:9
|
LL | struct S(i32, f32);
| ------------------- tuple struct defined here
...
LL | S() => {}
| ^^^ expected 2 fields, found 0
|
help: use `_` to explicitly ignore each field
|
LL | S(_, _) => {}
| ^^^^
help: use `..` to ignore all fields
|
LL | S(..) => {}
| ^^
error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
--> $DIR/pat-tuple-underfield.rs:27:9
|
LL | S(i32, f32),
| ----------- tuple variant defined here
...
LL | E::S(x) => {}
| ^^^^^^^ expected 2 fields, found 1
|
help: use `_` to explicitly ignore each field
|
LL | E::S(x, _) => {}
| ^^^
error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
--> $DIR/pat-tuple-underfield.rs:32:9
|
LL | S(i32, f32),
| ----------- tuple variant defined here
...
LL | E::S(_) => {}
| ^^^^^^^ expected 2 fields, found 1
|
help: use `_` to explicitly ignore each field
|
LL | E::S(_, _) => {}
| ^^^
help: use `..` to ignore all fields
|
LL | E::S(..) => {}
| ^^
error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields
--> $DIR/pat-tuple-underfield.rs:38:9
|
LL | S(i32, f32),
| ----------- tuple variant defined here
...
LL | E::S() => {}
| ^^^^^^ expected 2 fields, found 0
|
help: use `_` to explicitly ignore each field
|
LL | E::S(_, _) => {}
| ^^^^
help: use `..` to ignore all fields
|
LL | E::S(..) => {}
| ^^
error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 4 fields
--> $DIR/pat-tuple-underfield.rs:50:9
|
LL | struct Point4(i32, i32, i32, i32);
| ---------------------------------- tuple struct defined here
...
LL | Point4( a , _ ) => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 4 fields, found 2
|
help: use `_` to explicitly ignore each field
|
LL | Point4( a , _ , _, _) => {}
| ^^^^^^
help: use `..` to ignore the rest of the fields
|
LL | Point4( a , _ , ..) => {}
| ^^^^
error: aborting due to 8 previous errors
Some errors have detailed explanations: E0023, E0532.
For more information about an error, try `rustc --explain E0023`.