From 3ea744e2ac975456d14805100755d2e39a565e46 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Fri, 18 Dec 2020 17:03:45 -0500 Subject: [PATCH 01/47] Recommend panic::resume_unwind instead of panicking. Fixes https://github.com/rust-lang/rust/issues/79950. --- library/std/src/thread/mod.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 5d65f960fcd39..0d004a516f594 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -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`, 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 = crate::result::Result>; From 1f9a8a1620a677d668c981a8e6be3ce02ef06cd5 Mon Sep 17 00:00:00 2001 From: Camelid Date: Thu, 5 Nov 2020 00:44:42 -0800 Subject: [PATCH 02/47] Add a `std::io::read_to_string` function The equivalent of `std::fs::read_to_string`, but generalized to all `Read` impls. As the documentation on `std::io::read_to_string` says, the advantage of this function is that it means you don't have to create a variable first and it 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. It's friendlier to newcomers and better in most cases to use an explicit return value instead of an out parameter. --- library/std/src/io/mod.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index dfbf6c3f24443..7a1896e4e5901 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -945,6 +945,33 @@ pub trait Read { } } +/// Convenience function for [`Read::read_to_string`]. +/// +/// This avoids having to create a variable first and it 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.) +/// +/// # 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(reader: &mut R) -> Result { + 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 From 4ee6d1bf541a90206b9e5cba6840e774493abc57 Mon Sep 17 00:00:00 2001 From: Camelid Date: Wed, 30 Dec 2020 11:33:06 -0800 Subject: [PATCH 03/47] Add description independent of `Read::read_to_string` --- library/std/src/io/mod.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 7a1896e4e5901..1fdd82400d061 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -945,12 +945,13 @@ pub trait Read { } } -/// Convenience function for [`Read::read_to_string`]. +/// Read all bytes from a [reader][Read] into a new [`String`]. /// -/// This avoids having to create a variable first and it 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.) +/// 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.) /// /// # Examples /// From 588786a788a5606dd3f4b4769ecd2e0c26a3ad20 Mon Sep 17 00:00:00 2001 From: Camelid Date: Wed, 30 Dec 2020 11:44:03 -0800 Subject: [PATCH 04/47] Add error docs --- library/std/src/io/mod.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 1fdd82400d061..fdc0198945ef9 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -951,7 +951,14 @@ pub trait Read { /// 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.) +/// succeeded because otherwise your buffer will be empty or only partially full.) +/// +/// # 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 /// From 7ed824ebd158d24e0c570d0f4bedc3be566b4619 Mon Sep 17 00:00:00 2001 From: Lukas Lueg Date: Thu, 31 Dec 2020 22:14:19 +0100 Subject: [PATCH 05/47] Add Iterator::intersperse_with --- library/core/src/iter/adapters/intersperse.rs | 154 +++++++++++++++--- library/core/src/iter/adapters/mod.rs | 2 +- library/core/src/iter/mod.rs | 4 +- library/core/src/iter/traits/iterator.rs | 27 ++- library/core/tests/iter.rs | 30 ++++ 5 files changed, 192 insertions(+), 25 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index 362326725490f..adae47459f7f4 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -40,37 +40,149 @@ where } } - fn fold(mut self, init: B, mut f: F) -> B + fn fold(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - let mut accum = init; + let separator = self.separator; + intersperse_fold(self.iter, init, f, move || separator.clone(), self.needs_sep) + } + + fn size_hint(&self) -> (usize, Option) { + intersperse_size_hint(&self.iter, self.needs_sep) + } +} + +/// An iterator adapter that places a separator between all elements. +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +pub struct IntersperseWith +where + I: Iterator, +{ + separator: G, + iter: Peekable, + needs_sep: bool, +} + +// FIXME This manual implementation is needed as #[derive] misplaces trait bounds, +// requiring ::Item to be Debug on the struct-definition, which is +// not what we want. +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl crate::fmt::Debug for IntersperseWith +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() + } +} - // 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); - } +// FIXME This manual implementation is needed as #[derive] misplaces trait bounds, +// requiring ::Item to be Clone on the struct-definition, which is +// not what we want. +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl crate::clone::Clone for IntersperseWith +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(), } + } +} - let element = &self.separator; +impl IntersperseWith +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 } + } +} - self.iter.fold(accum, |mut accum, x| { - accum = f(accum, element.clone()); - accum = f(accum, x); - accum - }) +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl Iterator for IntersperseWith +where + I: Iterator, + G: FnMut() -> I::Item, +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + 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(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) { - 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) } } + +fn intersperse_size_hint(iter: &I, needs_sep: bool) -> (usize, Option) +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( + mut iter: Peekable, + 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 + }) +} diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 7dfbf32cea7b8..41a7b13232adf 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -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; diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 569de719d03d6..c57ba2bf62645 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -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; diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 633175702d870..91d7a47907a46 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -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, }; @@ -591,6 +591,31 @@ 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 separator = [" ❤️ ", " 😀 "].iter().copied().cycle(); + /// + /// let result = src.intersperse_with(|| separator.next().unwrap()).collect::(); + /// assert_eq!(result, "Hello ❤️ to 😀 all ❤️ people"); + /// ``` + #[inline] + #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] + fn intersperse_with(self, separator: G) -> IntersperseWith + 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. /// diff --git a/library/core/tests/iter.rs b/library/core/tests/iter.rs index 7376e7848eff5..691767edea6d9 100644 --- a/library/core/tests/iter.rs +++ b/library/core/tests/iter.rs @@ -3508,6 +3508,12 @@ pub fn extend_for_unit() { #[test] fn test_intersperse() { + let v = std::iter::empty().intersperse(0u32).collect::>(); + assert_eq!(v, vec![]); + + let v = std::iter::once(1).intersperse(0).collect::>(); + 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::().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::>(); + 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::>(); + assert_eq!(r, vec![0, 200, 1, 400, 2]); +} From 7a0ada0427ff1a8756f19f2bfb866a0c8461a029 Mon Sep 17 00:00:00 2001 From: Lukas Lueg Date: Thu, 7 Jan 2021 00:45:47 +0100 Subject: [PATCH 06/47] Remove FIXME-notes --- library/core/src/iter/adapters/intersperse.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index adae47459f7f4..9f5cca88206ef 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -65,9 +65,6 @@ where needs_sep: bool, } -// FIXME This manual implementation is needed as #[derive] misplaces trait bounds, -// requiring ::Item to be Debug on the struct-definition, which is -// not what we want. #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] impl crate::fmt::Debug for IntersperseWith where @@ -84,9 +81,6 @@ where } } -// FIXME This manual implementation is needed as #[derive] misplaces trait bounds, -// requiring ::Item to be Clone on the struct-definition, which is -// not what we want. #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] impl crate::clone::Clone for IntersperseWith where From f7d261c3b125c1d54bce9eae0da390f654d656b1 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Fri, 8 Jan 2021 18:00:25 -0500 Subject: [PATCH 07/47] Get rid of `DepConstructor` This removes fully 235 unused functions. --- .../rustc_middle/src/dep_graph/dep_node.rs | 45 ++++++------------- compiler/rustc_middle/src/dep_graph/mod.rs | 3 +- compiler/rustc_middle/src/mir/mono.rs | 4 +- 3 files changed, 17 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index b775846bba452..65e5301c96e9e 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -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 { 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; // We keep a lot of `DepNode`s in memory during compilation. It's not diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 22e9cc1cd3ee4..ea4d8c1299709 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -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; pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps; diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 698c25215968b..b8b5390ec40fe 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -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_data_structures::base_n; @@ -358,7 +358,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()) } } From ebe402dc9e708a8ed5e5860a7b30ea7826ab52a1 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 11 Jan 2021 07:27:03 -0500 Subject: [PATCH 08/47] Fix handling of malicious Readers in read_to_end --- library/std/src/io/mod.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 7ad9e446c5997..0bc0e0e8e83d8 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -390,7 +390,14 @@ where ret = Ok(g.len - start_len); break; } - Ok(n) => g.len += n, + Ok(n) => { + // We can't let g.len overflow which would result in the vec shrinking when the function returns. In + // particular, that could break read_to_string if the shortened buffer doesn't end on a UTF-8 boundary. + // The minimal check would just be a checked_add, but this assert is a bit more precise and should be + // just about the same cost. + assert!(n <= g.buf.len() - g.len); + g.len += n; + } Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => { ret = Err(e); From a9ef7983a629fea829955608d67f474f856da53c Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 11 Jan 2021 07:48:24 -0500 Subject: [PATCH 09/47] clean up control flow --- library/std/src/io/mod.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 0bc0e0e8e83d8..a054c434d0739 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -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 { @@ -386,10 +385,7 @@ where } match r.read(&mut g.buf[g.len..]) { - Ok(0) => { - ret = Ok(g.len - start_len); - break; - } + Ok(0) => return Ok(g.len - start_len), Ok(n) => { // We can't let g.len overflow which would result in the vec shrinking when the function returns. In // particular, that could break read_to_string if the shortened buffer doesn't end on a UTF-8 boundary. @@ -399,14 +395,9 @@ where 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(read: F, bufs: &mut [IoSliceMut<'_>]) -> Result From 5cb830397e8493f4bf923b411ec378cd00ce28f9 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 11 Jan 2021 17:13:50 -0500 Subject: [PATCH 10/47] make check a bit more clear --- library/std/src/io/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index a054c434d0739..af570ac6e30ba 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -384,14 +384,15 @@ where } } - match r.read(&mut g.buf[g.len..]) { + let buf = &mut g.buf[g.len..]; + match r.read(buf) { Ok(0) => return Ok(g.len - start_len), Ok(n) => { // We can't let g.len overflow which would result in the vec shrinking when the function returns. In // particular, that could break read_to_string if the shortened buffer doesn't end on a UTF-8 boundary. // The minimal check would just be a checked_add, but this assert is a bit more precise and should be // just about the same cost. - assert!(n <= g.buf.len() - g.len); + assert!(n <= buf.len()); g.len += n; } Err(ref e) if e.kind() == ErrorKind::Interrupted => {} From e6c07b0628938b0003ecbae0f60b588eebf474aa Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 11 Jan 2021 17:16:44 -0500 Subject: [PATCH 11/47] clarify docs a bit --- library/std/src/io/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index af570ac6e30ba..f73116ba106cc 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -388,10 +388,9 @@ where match r.read(buf) { Ok(0) => return Ok(g.len - start_len), Ok(n) => { - // We can't let g.len overflow which would result in the vec shrinking when the function returns. In - // particular, that could break read_to_string if the shortened buffer doesn't end on a UTF-8 boundary. - // The minimal check would just be a checked_add, but this assert is a bit more precise and should be - // just about the same cost. + // 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; } From 746329201546d38875bf1a7fa232453e833c01eb Mon Sep 17 00:00:00 2001 From: Camelid Date: Mon, 11 Jan 2021 19:17:13 -0800 Subject: [PATCH 12/47] Add docs on performance --- library/std/src/io/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index fdc0198945ef9..5540891c646d5 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -953,6 +953,19 @@ pub trait Read { /// 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`) From 16692ab66a6e2c62b416f606f144d60711c14414 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 13 Dec 2020 14:13:52 -0800 Subject: [PATCH 13/47] Suggest `_` and `..` if a pattern has too few fields For example, this code: struct S(i32, f32); let S(x) = S(0, 1.0); will make the compiler suggest either: let S(x, _) = S(0, 1.0); or: let S(x, ..) = S(0, 1.0); --- compiler/rustc_typeck/src/check/pat.rs | 29 +++++ .../tuple_struct_destructure_fail.stderr | 18 +++ src/test/ui/error-codes/E0023.stderr | 9 ++ ...7-pat-tup-scrut-ty-diff-less-fields.stderr | 9 ++ src/test/ui/issues/issue-72574-2.stderr | 9 ++ .../match/match-pattern-field-mismatch.stderr | 9 ++ src/test/ui/pattern/issue-74539.stderr | 9 ++ src/test/ui/pattern/pat-tuple-underfield.rs | 49 +++++++ .../ui/pattern/pat-tuple-underfield.stderr | 121 ++++++++++++++++++ 9 files changed, 262 insertions(+) create mode 100644 src/test/ui/pattern/pat-tuple-underfield.rs create mode 100644 src/test/ui/pattern/pat-tuple-underfield.stderr diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 5fc573a57ad0b..942be1007f062 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -15,10 +15,12 @@ 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; use std::collections::hash_map::Entry::{Occupied, Vacant}; +use std::iter; use super::report_unexpected_variant_res; @@ -1040,6 +1042,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { vec![(left, "(".to_string()), (right.shrink_to_hi(), ")".to_string())], Applicability::MachineApplicable, ); + } else if fields.len() > subpats.len() { + let after_fields_span = if pat_span == DUMMY_SP { + pat_span + } else { + pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi() + }; + + let mut wildcard_sugg = + iter::repeat("_").take(fields.len() - subpats.len()).collect::>().join(", "); + if !subpats.is_empty() { + wildcard_sugg = String::from(", ") + &wildcard_sugg; + } + + let rest_sugg = if subpats.is_empty() { "..".to_owned() } else { ", ..".to_owned() }; + + err.span_suggestion( + after_fields_span, + "use `_` to explicitly ignore each field", + wildcard_sugg, + Applicability::MaybeIncorrect, + ); + err.span_suggestion( + after_fields_span, + "use `..` to ignore all unmentioned fields", + rest_sugg, + Applicability::MaybeIncorrect, + ); } err.emit(); diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr index 0e7174e5b19d6..623e1d674d71a 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -31,6 +31,15 @@ LL | struct TupleStruct(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 unmentioned 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 unmentioned fields + | +LL | Enum::SingleVariant(_, ..) = Enum::SingleVariant(1, 2); + | ^^^^ error[E0070]: invalid left-hand side of assignment --> $DIR/tuple_struct_destructure_fail.rs:40:12 diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index a3610099294da..1d32eab15d33a 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -6,6 +6,15 @@ LL | Apple(String, String), ... LL | Fruit::Apple(a) => {}, | ^^^^^^^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | Fruit::Apple(a, _) => {}, + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | Fruit::Apple(a, ..) => {}, + | ^^^^ error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/E0023.rs:12:9 diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr index 6e8ea6bf618f2..38177d1515820 100644 --- a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr +++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr @@ -17,6 +17,15 @@ LL | struct P(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 unmentioned fields + | +LL | let P(..) = U {}; + | ^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr index 0a9c868af7af8..8edc6ca8f0ed6 100644 --- a/src/test/ui/issues/issue-72574-2.stderr +++ b/src/test/ui/issues/issue-72574-2.stderr @@ -26,6 +26,15 @@ 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 @ .., _) => {} + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | Binder(_a, _x @ .., ..) => {} + | ^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index c2298d6fbbf02..299b2d216db98 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -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 unmentioned fields + | +LL | Color::Rgb(_, _, ..) => { } + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/pattern/issue-74539.stderr b/src/test/ui/pattern/issue-74539.stderr index cbc90b5397d8b..7a73d39dbc0c6 100644 --- a/src/test/ui/pattern/issue-74539.stderr +++ b/src/test/ui/pattern/issue-74539.stderr @@ -26,6 +26,15 @@ LL | A(u8, u8), ... LL | E::A(x @ ..) => { | ^^^^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | E::A(x @ .., _) => { + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | E::A(x @ .., ..) => { + | ^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/pattern/pat-tuple-underfield.rs b/src/test/ui/pattern/pat-tuple-underfield.rs new file mode 100644 index 0000000000000..246dd0b37b659 --- /dev/null +++ b/src/test/ui/pattern/pat-tuple-underfield.rs @@ -0,0 +1,49 @@ +struct S(i32, f32); +enum E { + S(i32, f32), +} + +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 + //~| HELP use `..` to ignore all unmentioned fields + } + 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 unmentioned 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 unmentioned 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 + //~| HELP use `..` to ignore all unmentioned fields + } + 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 unmentioned 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 unmentioned 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 + } +} diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr new file mode 100644 index 0000000000000..5364053b8e526 --- /dev/null +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -0,0 +1,121 @@ +error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::S` + --> $DIR/pat-tuple-underfield.rs:45: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:8: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, _) => {} + | ^^^ +help: use `..` to ignore all unmentioned fields + | +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 unmentioned 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 unmentioned 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, _) => {} + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | E::S(x, ..) => {} + | ^^^^ + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields + --> $DIR/pat-tuple-underfield.rs:33: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 unmentioned fields + | +LL | E::S(_, ..) => {} + | ^^^^ + +error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields + --> $DIR/pat-tuple-underfield.rs:39: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 unmentioned fields + | +LL | E::S(..) => {} + | ^^ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0023, E0532. +For more information about an error, try `rustc --explain E0023`. From 5fe61a79cc5d26a0843b7169d1c95fbb3cbda0ba Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 18 Dec 2020 17:09:53 -0800 Subject: [PATCH 14/47] Simplify code Co-authored-by: Esteban Kuber --- compiler/rustc_typeck/src/check/pat.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 942be1007f062..db2f4eca0c9d0 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1049,8 +1049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi() }; - let mut wildcard_sugg = - iter::repeat("_").take(fields.len() - subpats.len()).collect::>().join(", "); + let mut wildcard_sugg = vec!["_"; fields.len() - subpats.len()].join(", "); if !subpats.is_empty() { wildcard_sugg = String::from(", ") + &wildcard_sugg; } From f3d9df54ee682d0b76909d27938b30c51ca5ec70 Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 18 Dec 2020 19:51:39 -0800 Subject: [PATCH 15/47] Suggest `Variant(..)` if all of the mentioned fields are `_` --- compiler/rustc_typeck/src/check/pat.rs | 33 ++++++++++++++----- .../tuple_struct_destructure_fail.stderr | 8 ++--- .../match/match-pattern-field-mismatch.stderr | 4 +-- .../ui/pattern/pat-tuple-underfield.stderr | 8 ++--- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index db2f4eca0c9d0..474aed39eb2fd 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -20,7 +20,6 @@ use rustc_trait_selection::traits::{ObligationCause, Pattern}; use std::cmp; use std::collections::hash_map::Entry::{Occupied, Vacant}; -use std::iter; use super::report_unexpected_variant_res; @@ -1048,26 +1047,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } 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; } - let rest_sugg = if subpats.is_empty() { "..".to_owned() } else { ", ..".to_owned() }; - err.span_suggestion( after_fields_span, "use `_` to explicitly ignore each field", wildcard_sugg, Applicability::MaybeIncorrect, ); - err.span_suggestion( - after_fields_span, - "use `..` to ignore all unmentioned fields", - rest_sugg, - Applicability::MaybeIncorrect, - ); + + if subpats.is_empty() || all_wildcards { + err.span_suggestion( + all_fields_span, + "use `..` to ignore all unmentioned fields", + String::from(".."), + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestion( + after_fields_span, + "use `..` to ignore all unmentioned fields", + String::from(", .."), + Applicability::MaybeIncorrect, + ); + } } err.emit(); diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr index 623e1d674d71a..dd1fbbbd3bbe5 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -38,8 +38,8 @@ LL | TupleStruct(_, _) = TupleStruct(1, 2); | ^^^ help: use `..` to ignore all unmentioned fields | -LL | TupleStruct(_, ..) = TupleStruct(1, 2); - | ^^^^ +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 @@ -65,8 +65,8 @@ LL | Enum::SingleVariant(_, _) = Enum::SingleVariant(1, 2); | ^^^ help: use `..` to ignore all unmentioned fields | -LL | Enum::SingleVariant(_, ..) = Enum::SingleVariant(1, 2); - | ^^^^ +LL | Enum::SingleVariant(..) = Enum::SingleVariant(1, 2); + | ^^ error[E0070]: invalid left-hand side of assignment --> $DIR/tuple_struct_destructure_fail.rs:40:12 diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index 299b2d216db98..1ee45ca1b1ea6 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -13,8 +13,8 @@ LL | Color::Rgb(_, _, _) => { } | ^^^ help: use `..` to ignore all unmentioned fields | -LL | Color::Rgb(_, _, ..) => { } - | ^^^^ +LL | Color::Rgb(..) => { } + | ^^ error: aborting due to previous error diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr index 5364053b8e526..b7a5402663917 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.stderr +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -40,8 +40,8 @@ LL | S(_, _) => {} | ^^^ help: use `..` to ignore all unmentioned fields | -LL | S(_, ..) => {} - | ^^^^ +LL | S(..) => {} + | ^^ error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields --> $DIR/pat-tuple-underfield.rs:20:9 @@ -94,8 +94,8 @@ LL | E::S(_, _) => {} | ^^^ help: use `..` to ignore all unmentioned fields | -LL | E::S(_, ..) => {} - | ^^^^ +LL | E::S(..) => {} + | ^^ error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields --> $DIR/pat-tuple-underfield.rs:39:9 From a5e8e6ec2df58bd50963af57bbd08d0526f119db Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 18 Dec 2020 19:56:14 -0800 Subject: [PATCH 16/47] Pluralize 'parenthesis' correctly It's 'parentheses', not 'parenthesis', when you have more than one. --- compiler/rustc_typeck/src/check/pat.rs | 10 +++++----- src/test/ui/error-codes/E0023.stderr | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 474aed39eb2fd..a7670624f307c 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1002,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);`. @@ -1015,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(()); // | ^ ^ @@ -1030,14 +1030,14 @@ 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, ); diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index 1d32eab15d33a..965cf28c79f91 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -43,7 +43,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)) => {}, | ^ ^ @@ -57,7 +57,7 @@ LL | Banana(()), LL | Fruit::Banana() => {}, | ^^^^^^^^^^^^^^^ expected 1 field, found 0 | -help: missing parenthesis +help: missing parentheses | LL | Fruit::Banana(()) => {}, | ^ ^ From fe82cc38a0b3e39b9425090e2107c0ba15760491 Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 18 Dec 2020 20:17:09 -0800 Subject: [PATCH 17/47] Specialize `..` help message for all fields vs. the rest --- compiler/rustc_typeck/src/check/pat.rs | 4 ++-- .../tuple_struct_destructure_fail.stderr | 4 ++-- src/test/ui/error-codes/E0023.stderr | 2 +- ...ue-67037-pat-tup-scrut-ty-diff-less-fields.stderr | 2 +- src/test/ui/issues/issue-72574-2.stderr | 2 +- .../ui/match/match-pattern-field-mismatch.stderr | 2 +- src/test/ui/pattern/issue-74539.stderr | 2 +- src/test/ui/pattern/pat-tuple-underfield.rs | 12 ++++++------ src/test/ui/pattern/pat-tuple-underfield.stderr | 12 ++++++------ 9 files changed, 21 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index a7670624f307c..43a69fe187431 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1071,14 +1071,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if subpats.is_empty() || all_wildcards { err.span_suggestion( all_fields_span, - "use `..` to ignore all unmentioned fields", + "use `..` to ignore all fields", String::from(".."), Applicability::MaybeIncorrect, ); } else { err.span_suggestion( after_fields_span, - "use `..` to ignore all unmentioned fields", + "use `..` to ignore the rest of the fields", String::from(", .."), Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr index dd1fbbbd3bbe5..c270593cac741 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -36,7 +36,7 @@ help: use `_` to explicitly ignore each field | LL | TupleStruct(_, _) = TupleStruct(1, 2); | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | TupleStruct(..) = TupleStruct(1, 2); | ^^ @@ -63,7 +63,7 @@ help: use `_` to explicitly ignore each field | LL | Enum::SingleVariant(_, _) = Enum::SingleVariant(1, 2); | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | Enum::SingleVariant(..) = Enum::SingleVariant(1, 2); | ^^ diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index 965cf28c79f91..aaaada518d3b7 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -11,7 +11,7 @@ help: use `_` to explicitly ignore each field | LL | Fruit::Apple(a, _) => {}, | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore the rest of the fields | LL | Fruit::Apple(a, ..) => {}, | ^^^^ diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr index 38177d1515820..9bdbf0bf9f40d 100644 --- a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr +++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr @@ -22,7 +22,7 @@ help: use `_` to explicitly ignore each field | LL | let P(_) = U {}; | ^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | let P(..) = U {}; | ^^ diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr index 8edc6ca8f0ed6..02497029960bf 100644 --- a/src/test/ui/issues/issue-72574-2.stderr +++ b/src/test/ui/issues/issue-72574-2.stderr @@ -31,7 +31,7 @@ help: use `_` to explicitly ignore each field | LL | Binder(_a, _x @ .., _) => {} | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore the rest of the fields | LL | Binder(_a, _x @ .., ..) => {} | ^^^^ diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index 1ee45ca1b1ea6..37839482b31a2 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -11,7 +11,7 @@ help: use `_` to explicitly ignore each field | LL | Color::Rgb(_, _, _) => { } | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | Color::Rgb(..) => { } | ^^ diff --git a/src/test/ui/pattern/issue-74539.stderr b/src/test/ui/pattern/issue-74539.stderr index 7a73d39dbc0c6..78249ed057ff8 100644 --- a/src/test/ui/pattern/issue-74539.stderr +++ b/src/test/ui/pattern/issue-74539.stderr @@ -31,7 +31,7 @@ help: use `_` to explicitly ignore each field | LL | E::A(x @ .., _) => { | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore the rest of the fields | LL | E::A(x @ .., ..) => { | ^^^^ diff --git a/src/test/ui/pattern/pat-tuple-underfield.rs b/src/test/ui/pattern/pat-tuple-underfield.rs index 246dd0b37b659..f306377e6e51d 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.rs +++ b/src/test/ui/pattern/pat-tuple-underfield.rs @@ -8,38 +8,38 @@ fn main() { S(x) => {} //~^ 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 unmentioned fields + //~| HELP use `..` to ignore the rest of the fields } 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 unmentioned fields + //~| 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 unmentioned fields + //~| 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 - //~| HELP use `..` to ignore all unmentioned fields + //~| HELP use `..` to ignore the rest of the fields } 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 unmentioned fields + //~| 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 unmentioned fields + //~| HELP use `..` to ignore all fields } match E::S(0, 1.0) { E::S => {} diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr index b7a5402663917..d1aaeaeafa47e 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.stderr +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -20,7 +20,7 @@ help: use `_` to explicitly ignore each field | LL | S(x, _) => {} | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore the rest of the fields | LL | S(x, ..) => {} | ^^^^ @@ -38,7 +38,7 @@ help: use `_` to explicitly ignore each field | LL | S(_, _) => {} | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | S(..) => {} | ^^ @@ -56,7 +56,7 @@ help: use `_` to explicitly ignore each field | LL | S(_, _) => {} | ^^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | S(..) => {} | ^^ @@ -74,7 +74,7 @@ help: use `_` to explicitly ignore each field | LL | E::S(x, _) => {} | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore the rest of the fields | LL | E::S(x, ..) => {} | ^^^^ @@ -92,7 +92,7 @@ help: use `_` to explicitly ignore each field | LL | E::S(_, _) => {} | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | E::S(..) => {} | ^^ @@ -110,7 +110,7 @@ help: use `_` to explicitly ignore each field | LL | E::S(_, _) => {} | ^^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | E::S(..) => {} | ^^ From 9959d6deedbf39d58fac06949596073d9c0dbb23 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 20 Dec 2020 14:43:07 -0800 Subject: [PATCH 18/47] Only suggest `..` if more than one field is missing --- compiler/rustc_typeck/src/check/pat.rs | 33 +++++---- .../tuple_struct_destructure_fail.stderr | 28 +++----- src/test/ui/error-codes/E0023.stderr | 14 ++-- ...7-pat-tup-scrut-ty-diff-less-fields.stderr | 14 ++-- src/test/ui/issues/issue-72574-2.stderr | 14 ++-- .../match/match-pattern-field-mismatch.stderr | 14 ++-- src/test/ui/pattern/issue-74539.stderr | 14 ++-- src/test/ui/pattern/pat-tuple-underfield.rs | 4 -- .../ui/pattern/pat-tuple-underfield.stderr | 68 ++++++------------- 9 files changed, 68 insertions(+), 135 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 43a69fe187431..a863fc95e0ea1 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1061,27 +1061,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { wildcard_sugg = String::from(", ") + &wildcard_sugg; } - err.span_suggestion( + err.span_suggestion_short( after_fields_span, "use `_` to explicitly ignore each field", wildcard_sugg, Applicability::MaybeIncorrect, ); - if subpats.is_empty() || all_wildcards { - err.span_suggestion( - all_fields_span, - "use `..` to ignore all fields", - String::from(".."), - Applicability::MaybeIncorrect, - ); - } else { - err.span_suggestion( - after_fields_span, - "use `..` to ignore the rest of the fields", - String::from(", .."), - Applicability::MaybeIncorrect, - ); + // Only suggest `..` if more than one field is missing. + if fields.len() - subpats.len() > 1 { + if subpats.is_empty() || all_wildcards { + err.span_suggestion_short( + all_fields_span, + "use `..` to ignore all fields", + String::from(".."), + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestion_short( + after_fields_span, + "use `..` to ignore the rest of the fields", + String::from(", .."), + Applicability::MaybeIncorrect, + ); + } } } diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr index c270593cac741..42859406e178d 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -30,16 +30,10 @@ LL | struct TupleStruct(S, T); | ------------------------------- tuple struct defined here ... 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); - | ^^ + | ^^^^^^^^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/tuple_struct_destructure_fail.rs:34:5 @@ -57,16 +51,10 @@ LL | SingleVariant(S, T) | ------------------- tuple variant defined here ... 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); - | ^^ + | ^^^^^^^^^^^^^^^^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0070]: invalid left-hand side of assignment --> $DIR/tuple_struct_destructure_fail.rs:40:12 diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index aaaada518d3b7..0c6f496cf4353 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -5,16 +5,10 @@ LL | Apple(String, String), | --------------------- tuple variant defined here ... LL | Fruit::Apple(a) => {}, - | ^^^^^^^^^^^^^^^ expected 2 fields, found 1 - | -help: use `_` to explicitly ignore each field - | -LL | Fruit::Apple(a, _) => {}, - | ^^^ -help: use `..` to ignore the rest of the fields - | -LL | Fruit::Apple(a, ..) => {}, - | ^^^^ + | ^^^^^^^^^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/E0023.rs:12:9 diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr index 9bdbf0bf9f40d..86be8e7db4e6f 100644 --- a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr +++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr @@ -16,16 +16,10 @@ LL | struct P(T); // 1 type parameter wanted | --------------- tuple struct defined here ... 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 {}; - | ^^ + | ^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 1 field, found 0 error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr index 02497029960bf..9479e365aee68 100644 --- a/src/test/ui/issues/issue-72574-2.stderr +++ b/src/test/ui/issues/issue-72574-2.stderr @@ -25,16 +25,10 @@ LL | struct Binder(i32, i32, i32); | ----------------------------- tuple struct defined here ... LL | Binder(_a, _x @ ..) => {} - | ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 2 - | -help: use `_` to explicitly ignore each field - | -LL | Binder(_a, _x @ .., _) => {} - | ^^^ -help: use `..` to ignore the rest of the fields - | -LL | Binder(_a, _x @ .., ..) => {} - | ^^^^ + | ^^^^^^^^^^^^^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 3 fields, found 2 error: aborting due to 3 previous errors diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index 37839482b31a2..0bb5e726ccbd8 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -5,16 +5,10 @@ LL | Rgb(usize, usize, usize), | ------------------------ tuple variant defined here ... 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(..) => { } - | ^^ + | ^^^^^^^^^^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 3 fields, found 2 error: aborting due to previous error diff --git a/src/test/ui/pattern/issue-74539.stderr b/src/test/ui/pattern/issue-74539.stderr index 78249ed057ff8..49011d83e5075 100644 --- a/src/test/ui/pattern/issue-74539.stderr +++ b/src/test/ui/pattern/issue-74539.stderr @@ -25,16 +25,10 @@ LL | A(u8, u8), | --------- tuple variant defined here ... LL | E::A(x @ ..) => { - | ^^^^^^^^^^^^ expected 2 fields, found 1 - | -help: use `_` to explicitly ignore each field - | -LL | E::A(x @ .., _) => { - | ^^^ -help: use `..` to ignore the rest of the fields - | -LL | E::A(x @ .., ..) => { - | ^^^^ + | ^^^^^^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error: aborting due to 3 previous errors diff --git a/src/test/ui/pattern/pat-tuple-underfield.rs b/src/test/ui/pattern/pat-tuple-underfield.rs index f306377e6e51d..f86d617801455 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.rs +++ b/src/test/ui/pattern/pat-tuple-underfield.rs @@ -8,13 +8,11 @@ fn main() { S(x) => {} //~^ 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 the rest of the fields } 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() => {} @@ -27,13 +25,11 @@ fn main() { E::S(x) => {} //~^ 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 the rest of the fields } 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() => {} diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr index d1aaeaeafa47e..6e7afd8e57b1d 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.stderr +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -1,5 +1,5 @@ error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::S` - --> $DIR/pat-tuple-underfield.rs:45:9 + --> $DIR/pat-tuple-underfield.rs:41:9 | LL | S(i32, f32), | ----------- `E::S` defined here @@ -14,37 +14,25 @@ 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, _) => {} - | ^^^ -help: use `..` to ignore the rest of the fields - | -LL | S(x, ..) => {} - | ^^^^ + | ^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields - --> $DIR/pat-tuple-underfield.rs:14:9 + --> $DIR/pat-tuple-underfield.rs:13: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(..) => {} - | ^^ + | ^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields - --> $DIR/pat-tuple-underfield.rs:20:9 + --> $DIR/pat-tuple-underfield.rs:18:9 | LL | struct S(i32, f32); | ------------------- tuple struct defined here @@ -62,43 +50,31 @@ LL | S(..) => {} | ^^ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:27:9 + --> $DIR/pat-tuple-underfield.rs:25: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, _) => {} - | ^^^ -help: use `..` to ignore the rest of the fields - | -LL | E::S(x, ..) => {} - | ^^^^ + | ^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:33:9 + --> $DIR/pat-tuple-underfield.rs:30: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(..) => {} - | ^^ + | ^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:39:9 + --> $DIR/pat-tuple-underfield.rs:35:9 | LL | S(i32, f32), | ----------- tuple variant defined here From 1bce77576964e069833edb1b3b6ca5baa68ae65e Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 12 Jan 2021 16:47:04 -0800 Subject: [PATCH 19/47] Add a test case with lots of whitespace --- src/test/ui/pattern/pat-tuple-underfield.rs | 8 +++++ .../ui/pattern/pat-tuple-underfield.stderr | 34 ++++++++++++++----- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/test/ui/pattern/pat-tuple-underfield.rs b/src/test/ui/pattern/pat-tuple-underfield.rs index f86d617801455..50f8a855d3639 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.rs +++ b/src/test/ui/pattern/pat-tuple-underfield.rs @@ -2,6 +2,7 @@ struct S(i32, f32); enum E { S(i32, f32), } +struct Point4(i32, i32, i32, i32); fn main() { match S(0, 1.0) { @@ -42,4 +43,11 @@ fn main() { //~^ 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 + } } diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr index 6e7afd8e57b1d..df6b216272e30 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.stderr +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -1,5 +1,5 @@ error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::S` - --> $DIR/pat-tuple-underfield.rs:41:9 + --> $DIR/pat-tuple-underfield.rs:42:9 | LL | S(i32, f32), | ----------- `E::S` defined here @@ -8,7 +8,7 @@ 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:8:9 + --> $DIR/pat-tuple-underfield.rs:9:9 | LL | struct S(i32, f32); | ------------------- tuple struct defined here @@ -20,7 +20,7 @@ LL | S(x) => {} | expected 2 fields, found 1 error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields - --> $DIR/pat-tuple-underfield.rs:13:9 + --> $DIR/pat-tuple-underfield.rs:14:9 | LL | struct S(i32, f32); | ------------------- tuple struct defined here @@ -32,7 +32,7 @@ LL | S(_) => {} | expected 2 fields, found 1 error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields - --> $DIR/pat-tuple-underfield.rs:18:9 + --> $DIR/pat-tuple-underfield.rs:19:9 | LL | struct S(i32, f32); | ------------------- tuple struct defined here @@ -50,7 +50,7 @@ LL | S(..) => {} | ^^ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:25:9 + --> $DIR/pat-tuple-underfield.rs:26:9 | LL | S(i32, f32), | ----------- tuple variant defined here @@ -62,7 +62,7 @@ LL | E::S(x) => {} | expected 2 fields, found 1 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:30:9 + --> $DIR/pat-tuple-underfield.rs:31:9 | LL | S(i32, f32), | ----------- tuple variant defined here @@ -74,7 +74,7 @@ LL | E::S(_) => {} | expected 2 fields, found 1 error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:35:9 + --> $DIR/pat-tuple-underfield.rs:36:9 | LL | S(i32, f32), | ----------- tuple variant defined here @@ -91,7 +91,25 @@ help: use `..` to ignore all fields LL | E::S(..) => {} | ^^ -error: aborting due to 7 previous errors +error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 4 fields + --> $DIR/pat-tuple-underfield.rs:48: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`. From d7307a71f5e1893f7bd69ff160ce38dc97b5d195 Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 12 Jan 2021 19:06:20 -0800 Subject: [PATCH 20/47] Always show suggestions in their own subwindows --- compiler/rustc_typeck/src/check/pat.rs | 6 +-- .../tuple_struct_destructure_fail.stderr | 20 ++++++---- src/test/ui/error-codes/E0023.stderr | 10 +++-- ...7-pat-tup-scrut-ty-diff-less-fields.stderr | 10 +++-- src/test/ui/issues/issue-72574-2.stderr | 10 +++-- .../match/match-pattern-field-mismatch.stderr | 10 +++-- src/test/ui/pattern/issue-74539.stderr | 10 +++-- .../ui/pattern/pat-tuple-underfield.stderr | 40 +++++++++++-------- 8 files changed, 69 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index a863fc95e0ea1..e176389f0e279 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1061,7 +1061,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { wildcard_sugg = String::from(", ") + &wildcard_sugg; } - err.span_suggestion_short( + err.span_suggestion_verbose( after_fields_span, "use `_` to explicitly ignore each field", wildcard_sugg, @@ -1071,14 +1071,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only suggest `..` if more than one field is missing. if fields.len() - subpats.len() > 1 { if subpats.is_empty() || all_wildcards { - err.span_suggestion_short( + err.span_suggestion_verbose( all_fields_span, "use `..` to ignore all fields", String::from(".."), Applicability::MaybeIncorrect, ); } else { - err.span_suggestion_short( + err.span_suggestion_verbose( after_fields_span, "use `..` to ignore the rest of the fields", String::from(", .."), diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr index 42859406e178d..8c20bb4fb833c 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -30,10 +30,12 @@ LL | struct TupleStruct(S, T); | ------------------------------- tuple struct defined here ... LL | TupleStruct(_) = TupleStruct(1, 2); - | ^^^^^^^^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^^^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +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 @@ -51,10 +53,12 @@ LL | SingleVariant(S, T) | ------------------- tuple variant defined here ... LL | Enum::SingleVariant(_) = Enum::SingleVariant(1, 2); - | ^^^^^^^^^^^^^^^^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | Enum::SingleVariant(_, _) = Enum::SingleVariant(1, 2); + | ^^^ error[E0070]: invalid left-hand side of assignment --> $DIR/tuple_struct_destructure_fail.rs:40:12 diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index 0c6f496cf4353..832eba6972213 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -5,10 +5,12 @@ LL | Apple(String, String), | --------------------- tuple variant defined here ... LL | Fruit::Apple(a) => {}, - | ^^^^^^^^^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^^^^^^^^^^^^ 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 diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr index 86be8e7db4e6f..46ffac48c1bad 100644 --- a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr +++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr @@ -16,10 +16,12 @@ LL | struct P(T); // 1 type parameter wanted | --------------- tuple struct defined here ... LL | let P() = U {}; - | ^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 1 field, found 0 + | ^^^ expected 1 field, found 0 + | +help: use `_` to explicitly ignore each field + | +LL | let P(_) = U {}; + | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr index 9479e365aee68..a1e8ec1677db5 100644 --- a/src/test/ui/issues/issue-72574-2.stderr +++ b/src/test/ui/issues/issue-72574-2.stderr @@ -25,10 +25,12 @@ LL | struct Binder(i32, i32, i32); | ----------------------------- tuple struct defined here ... LL | Binder(_a, _x @ ..) => {} - | ^^^^^^^^^^^^^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 3 fields, found 2 + | ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 2 + | +help: use `_` to explicitly ignore each field + | +LL | Binder(_a, _x @ .., _) => {} + | ^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index 0bb5e726ccbd8..04f8cab900e1b 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -5,10 +5,12 @@ LL | Rgb(usize, usize, usize), | ------------------------ tuple variant defined here ... LL | Color::Rgb(_, _) => { } - | ^^^^^^^^^^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 3 fields, found 2 + | ^^^^^^^^^^^^^^^^ expected 3 fields, found 2 + | +help: use `_` to explicitly ignore each field + | +LL | Color::Rgb(_, _, _) => { } + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/pattern/issue-74539.stderr b/src/test/ui/pattern/issue-74539.stderr index 49011d83e5075..f7644c19ea0d9 100644 --- a/src/test/ui/pattern/issue-74539.stderr +++ b/src/test/ui/pattern/issue-74539.stderr @@ -25,10 +25,12 @@ LL | A(u8, u8), | --------- tuple variant defined here ... LL | E::A(x @ ..) => { - | ^^^^^^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | E::A(x @ .., _) => { + | ^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr index df6b216272e30..cdf7cfe30054d 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.stderr +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -14,10 +14,12 @@ LL | struct S(i32, f32); | ------------------- tuple struct defined here ... LL | S(x) => {} - | ^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^ 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 @@ -26,10 +28,12 @@ LL | struct S(i32, f32); | ------------------- tuple struct defined here ... LL | S(_) => {} - | ^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | S(_, _) => {} + | ^^^ error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields --> $DIR/pat-tuple-underfield.rs:19:9 @@ -56,10 +60,12 @@ LL | S(i32, f32), | ----------- tuple variant defined here ... LL | E::S(x) => {} - | ^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^^^^ 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:31:9 @@ -68,10 +74,12 @@ LL | S(i32, f32), | ----------- tuple variant defined here ... LL | E::S(_) => {} - | ^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | E::S(_, _) => {} + | ^^^ error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields --> $DIR/pat-tuple-underfield.rs:36:9 From c3f7429fb4edae31b5e4838404aa2a11117dabcc Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 12 Jan 2021 20:52:06 -0800 Subject: [PATCH 21/47] Use better ICE message when no MIR is available The ICE message is somewhat confusing and overly specific - the issue is that there's no MIR available. This should make debugging these ICEs easier since the error tells you what's actually wrong, not what it was trying to do when it failed. cc https://github.com/rust-lang/rust/pull/80952#issuecomment-759198841 --- compiler/rustc_mir/src/monomorphize/collector.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 6370ead97e798..9a191e94b5dc7 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -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 From 7e83fece9159463746a53242b2c6c795a47ccf9b Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Wed, 13 Jan 2021 15:14:11 +1000 Subject: [PATCH 22/47] remove unstable deprecated Vec::remove_item --- library/alloc/src/vec/mod.rs | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 2a83eb33fe3ec..fc9e108a3c660 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1950,27 +1950,6 @@ impl Vec { } } -impl Vec { - /// 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(&mut self, item: &V) -> Option - where - T: PartialEq, - { - let pos = self.iter().position(|x| *x == *item)?; - Some(self.remove(pos)) - } -} - //////////////////////////////////////////////////////////////////////////////// // Internal methods and functions //////////////////////////////////////////////////////////////////////////////// From 6bfd987aa03c75e7bb300b13d1956b2b3b4b2d11 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 12 Jan 2021 20:42:46 -0800 Subject: [PATCH 23/47] Update books --- src/doc/book | 2 +- src/doc/embedded-book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/book b/src/doc/book index 5bb44f8b5b0aa..ac57a0ddd23d1 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 5bb44f8b5b0aa105c8b22602e9b18800484afa21 +Subproject commit ac57a0ddd23d173b26731ccf939f3ba729753275 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index ba34b8a968f95..ceec19e873be8 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit ba34b8a968f9531d38c4dc4411d5568b7c076bfe +Subproject commit ceec19e873be87c6ee5666b030c6bb612f889a96 diff --git a/src/doc/nomicon b/src/doc/nomicon index a5a48441d411f..a8584998eacde 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit a5a48441d411f61556b57d762b03d6874afe575d +Subproject commit a8584998eacdea7106a1dfafcbf6c1c06fcdf925 diff --git a/src/doc/reference b/src/doc/reference index b278478b76617..50af691f83893 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit b278478b766178491a8b6f67afa4bcd6b64d977a +Subproject commit 50af691f838937c300b47812d0507c6d88c14f97 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 1cce0737d6a7d..03e23af01f0b4 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 1cce0737d6a7d3ceafb139b4a206861fb1dcb2ab +Subproject commit 03e23af01f0b4f83a3a513da280e1ca92587f2ec From e8c87935e0004ff784ad361a5bac39d7677c3f4f Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 12 Jan 2021 20:39:51 -0800 Subject: [PATCH 24/47] Include `..` suggestion if fields are all wildcards --- compiler/rustc_typeck/src/check/pat.rs | 5 +++-- .../tuple_struct_destructure_fail.stderr | 8 ++++++++ ...7-pat-tup-scrut-ty-diff-less-fields.stderr | 4 ++++ .../match/match-pattern-field-mismatch.stderr | 4 ++++ src/test/ui/pattern/pat-tuple-underfield.rs | 2 ++ .../ui/pattern/pat-tuple-underfield.stderr | 20 +++++++++++++------ 6 files changed, 35 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index e176389f0e279..ecc6e8599ad01 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1068,8 +1068,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); - // Only suggest `..` if more than one field is missing. - if fields.len() - subpats.len() > 1 { + // 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, diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr index 8c20bb4fb833c..c270593cac741 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -36,6 +36,10 @@ 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 @@ -59,6 +63,10 @@ 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 diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr index 46ffac48c1bad..9bdbf0bf9f40d 100644 --- a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr +++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr @@ -22,6 +22,10 @@ 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 diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index 04f8cab900e1b..37839482b31a2 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -11,6 +11,10 @@ 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 diff --git a/src/test/ui/pattern/pat-tuple-underfield.rs b/src/test/ui/pattern/pat-tuple-underfield.rs index 50f8a855d3639..ed852a47bb4ee 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.rs +++ b/src/test/ui/pattern/pat-tuple-underfield.rs @@ -14,6 +14,7 @@ fn main() { 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() => {} @@ -31,6 +32,7 @@ fn main() { 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() => {} diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr index cdf7cfe30054d..76323d9a7bf56 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.stderr +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -1,5 +1,5 @@ error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::S` - --> $DIR/pat-tuple-underfield.rs:42:9 + --> $DIR/pat-tuple-underfield.rs:44:9 | LL | S(i32, f32), | ----------- `E::S` defined here @@ -34,9 +34,13 @@ 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:19:9 + --> $DIR/pat-tuple-underfield.rs:20:9 | LL | struct S(i32, f32); | ------------------- tuple struct defined here @@ -54,7 +58,7 @@ LL | S(..) => {} | ^^ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:26:9 + --> $DIR/pat-tuple-underfield.rs:27:9 | LL | S(i32, f32), | ----------- tuple variant defined here @@ -68,7 +72,7 @@ LL | E::S(x, _) => {} | ^^^ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:31:9 + --> $DIR/pat-tuple-underfield.rs:32:9 | LL | S(i32, f32), | ----------- tuple variant defined here @@ -80,9 +84,13 @@ 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:36:9 + --> $DIR/pat-tuple-underfield.rs:38:9 | LL | S(i32, f32), | ----------- tuple variant defined here @@ -100,7 +108,7 @@ LL | E::S(..) => {} | ^^ error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 4 fields - --> $DIR/pat-tuple-underfield.rs:48:9 + --> $DIR/pat-tuple-underfield.rs:50:9 | LL | struct Point4(i32, i32, i32, i32); | ---------------------------------- tuple struct defined here From d65cb6ebcedadbfdf190975228e5db7a5c8f1555 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Wed, 13 Jan 2021 14:39:19 +1000 Subject: [PATCH 25/47] deprecate atomic::spin_loop_hint in favour of hint::spin_loop --- library/alloc/src/sync/tests.rs | 2 +- library/core/src/sync/atomic.rs | 27 +++++++++---------- library/std/src/sys/hermit/mutex.rs | 5 ++-- .../std/src/sys/sgx/waitqueue/spin_mutex.rs | 5 ++-- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs index e8e1e66da5ed4..5067af1d4ff68 100644 --- a/library/alloc/src/sync/tests.rs +++ b/library/alloc/src/sync/tests.rs @@ -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(); } diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index d03c19e51f3fa..decc1fc622100 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -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 fmt::Pointer for AtomicPtr { 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() +} diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs index f988a019cfedb..885389ca54cd4 100644 --- a/library/std/src/sys/hermit/mutex.rs +++ b/library/std/src/sys/hermit/mutex.rs @@ -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 Spinlock { 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(); } } diff --git a/library/std/src/sys/sgx/waitqueue/spin_mutex.rs b/library/std/src/sys/sgx/waitqueue/spin_mutex.rs index 9140041c58414..7f1a671bab4eb 100644 --- a/library/std/src/sys/sgx/waitqueue/spin_mutex.rs +++ b/library/std/src/sys/sgx/waitqueue/spin_mutex.rs @@ -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 { @@ -32,7 +33,7 @@ impl SpinMutex { match self.try_lock() { None => { while self.lock.load(Ordering::Relaxed) { - spin_loop_hint() + hint::spin_loop() } } Some(guard) => return guard, From 697b20ff08f98fff289ef9a861ac9dea5e7f9314 Mon Sep 17 00:00:00 2001 From: trevor arjeski Date: Wed, 13 Jan 2021 13:49:46 +0300 Subject: [PATCH 26/47] Fixed incorrect doc comment ">" is right alignment, not left --- library/core/src/fmt/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 0c65c1c9eb7e9..7e817edeec1ee 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -1555,7 +1555,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"); /// ``` From 64c1b0d614949f405d8b4498a3b2ea59d9ec230e Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 13 Jan 2021 12:15:42 +0100 Subject: [PATCH 27/47] Fix -Cpasses=list and llvm version print with -vV --- compiler/rustc_driver/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index f434673c39e10..c668c94bb08c4 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -808,7 +808,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(); } } @@ -1096,7 +1096,7 @@ pub fn handle_options(args: &[String]) -> Option { } 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; From 5b1316f78152a9c066b357ea9addf803d48e114a Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 12 Dec 2020 21:31:54 +0000 Subject: [PATCH 28/47] unix ExitStatus: Do not treat WIFSTOPPED as WIFSIGNALED A unix wait status can contain, at least, exit statuses, termination signals, and stop signals. WTERMSIG is only valid if WIFSIGNALED. https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html It will not be easy to experience this bug with `Command`, because that doesn't pass WUNTRACED. But you could make an ExitStatus containing, say, a WIFSTOPPED, from a call to one of the libc wait functions. (In the WIFSTOPPED case, there is WSTOPSIG. But a stop signal is encoded differently to a termination signal, so WTERMSIG and WSTOPSIG are by no means the same.) Signed-off-by: Ian Jackson --- library/std/src/sys/unix/process/process_unix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index a590c74435639..629180fd71231 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -479,7 +479,7 @@ impl ExitStatus { } pub fn signal(&self) -> Option { - if !self.exited() { Some(libc::WTERMSIG(self.0)) } else { None } + if libc::WIFSIGNALED(self.0) { Some(libc::WTERMSIG(self.0)) } else { None } } } From 12d62aa436ee3a7ae0a55f63c4089c09fe140ccb Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 12 Dec 2020 21:37:34 +0000 Subject: [PATCH 29/47] unix ExitStatus: Clarify docs for .signal() We need to be clear that this never returns WSTOPSIG. That is, if WIFSTOPPED, the return value is None. Signed-off-by: Ian Jackson --- library/std/src/sys/unix/ext/process.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs index 3615a8a5ee8b0..ab961a284d51b 100644 --- a/library/std/src/sys/unix/ext/process.rs +++ b/library/std/src/sys/unix/ext/process.rs @@ -171,6 +171,8 @@ pub trait ExitStatusExt { fn from_raw(raw: i32) -> Self; /// If the process was terminated by a signal, returns that signal. + /// + /// Ie, if `WIFSIGNALED`, this returns `WTERMSIG`. #[stable(feature = "rust1", since = "1.0.0")] fn signal(&self) -> Option; } From 530270f94a3d9f1c23257ad1c9c93675b31ecf6a Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 12 Dec 2020 21:41:55 +0000 Subject: [PATCH 30/47] unix ExitStatus: Provide .into_raw() Signed-off-by: Ian Jackson --- library/std/src/sys/unix/ext/process.rs | 8 ++++++++ library/std/src/sys/unix/process/process_unix.rs | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs index ab961a284d51b..4b65629e2b368 100644 --- a/library/std/src/sys/unix/ext/process.rs +++ b/library/std/src/sys/unix/ext/process.rs @@ -175,6 +175,10 @@ pub trait ExitStatusExt { /// Ie, if `WIFSIGNALED`, this returns `WTERMSIG`. #[stable(feature = "rust1", since = "1.0.0")] fn signal(&self) -> Option; + + /// Returns the underlying raw `wait` status. + #[unstable(feature = "unix_process_wait_more", issue = "none")] + fn into_raw(self) -> i32; } #[stable(feature = "rust1", since = "1.0.0")] @@ -186,6 +190,10 @@ impl ExitStatusExt for process::ExitStatus { fn signal(&self) -> Option { self.as_inner().signal() } + + fn into_raw(self) -> i32 { + self.as_inner().into_raw().into() + } } #[stable(feature = "process_extensions", since = "1.2.0")] diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 629180fd71231..f1cf402805781 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -481,6 +481,10 @@ impl ExitStatus { pub fn signal(&self) -> Option { if libc::WIFSIGNALED(self.0) { Some(libc::WTERMSIG(self.0)) } else { None } } + + pub fn into_raw(&self) -> c_int { + self.0 + } } /// Converts a raw `c_int` to a type-safe `ExitStatus` by wrapping it without copying. From 3f05051d6bcb7b8562577324d59a2435a40992e9 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 12 Dec 2020 21:44:13 +0000 Subject: [PATCH 31/47] unix ExitStatus: Provide .core_dumped This is essential for proper reporting of child process status on Unix. Signed-off-by: Ian Jackson --- library/std/src/sys/unix/ext/process.rs | 8 ++++++++ library/std/src/sys/unix/process/process_unix.rs | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs index 4b65629e2b368..827cc0b9828b4 100644 --- a/library/std/src/sys/unix/ext/process.rs +++ b/library/std/src/sys/unix/ext/process.rs @@ -176,6 +176,10 @@ pub trait ExitStatusExt { #[stable(feature = "rust1", since = "1.0.0")] fn signal(&self) -> Option; + /// If the process was terminated by a signal, says whether it dumped core. + #[unstable(feature = "unix_process_wait_more", issue = "none")] + fn core_dumped(&self) -> bool; + /// Returns the underlying raw `wait` status. #[unstable(feature = "unix_process_wait_more", issue = "none")] fn into_raw(self) -> i32; @@ -191,6 +195,10 @@ impl ExitStatusExt for process::ExitStatus { self.as_inner().signal() } + fn core_dumped(&self) -> bool { + self.as_inner().core_dumped() + } + fn into_raw(self) -> i32 { self.as_inner().into_raw().into() } diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index f1cf402805781..99b1011578a5a 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -482,6 +482,10 @@ impl ExitStatus { 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 into_raw(&self) -> c_int { self.0 } From f060b9e0d9277ae522a34ca06312c5857c9aadb0 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 12 Dec 2020 21:47:47 +0000 Subject: [PATCH 32/47] unix ExitStatus: Provide .stopped_signal() Necessary to handle WIFSTOPPED. Signed-off-by: Ian Jackson --- library/std/src/sys/unix/ext/process.rs | 11 +++++++++++ library/std/src/sys/unix/process/process_unix.rs | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs index 827cc0b9828b4..5efe08340f488 100644 --- a/library/std/src/sys/unix/ext/process.rs +++ b/library/std/src/sys/unix/ext/process.rs @@ -180,6 +180,13 @@ pub trait ExitStatusExt { #[unstable(feature = "unix_process_wait_more", issue = "none")] fn core_dumped(&self) -> bool; + /// If the process was stopped by a signal, returns that signal. + /// + /// Ie, 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 = "none")] + fn stopped_signal(&self) -> Option; + /// Returns the underlying raw `wait` status. #[unstable(feature = "unix_process_wait_more", issue = "none")] fn into_raw(self) -> i32; @@ -199,6 +206,10 @@ impl ExitStatusExt for process::ExitStatus { self.as_inner().core_dumped() } + fn stopped_signal(&self) -> Option { + self.as_inner().stopped_signal() + } + fn into_raw(self) -> i32 { self.as_inner().into_raw().into() } diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 99b1011578a5a..069a1145f7645 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -486,6 +486,10 @@ impl ExitStatus { libc::WIFSIGNALED(self.0) && libc::WCOREDUMP(self.0) } + pub fn stopped_signal(&self) -> Option { + if libc::WIFSTOPPED(self.0) { Some(libc::WSTOPSIG(self.0)) } else { None } + } + pub fn into_raw(&self) -> c_int { self.0 } From 42ea8f64347e8c57972a043b00e6c02c9973e7df Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 12 Dec 2020 21:52:17 +0000 Subject: [PATCH 33/47] unix ExitStatus: Provide .continued() Signed-off-by: Ian Jackson --- library/std/src/sys/unix/ext/process.rs | 11 +++++++++++ library/std/src/sys/unix/process/process_unix.rs | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs index 5efe08340f488..6ab109cdb08c2 100644 --- a/library/std/src/sys/unix/ext/process.rs +++ b/library/std/src/sys/unix/ext/process.rs @@ -187,6 +187,13 @@ pub trait ExitStatusExt { #[unstable(feature = "unix_process_wait_more", issue = "none")] fn stopped_signal(&self) -> Option; + /// 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 = "none")] + fn continued(&self) -> bool; + /// Returns the underlying raw `wait` status. #[unstable(feature = "unix_process_wait_more", issue = "none")] fn into_raw(self) -> i32; @@ -210,6 +217,10 @@ impl ExitStatusExt for process::ExitStatus { self.as_inner().stopped_signal() } + fn continued(&self) -> bool { + self.as_inner().continued() + } + fn into_raw(self) -> i32 { self.as_inner().into_raw().into() } diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 069a1145f7645..945b43678a919 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -490,6 +490,10 @@ impl ExitStatus { 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 } From 29c851aef6c75e4ddedca1d5603daf3a25bd1ce1 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sun, 13 Dec 2020 11:03:17 +0000 Subject: [PATCH 34/47] Replace `Ie` with `In other words` Co-authored-by: Joshua Nelson --- library/std/src/sys/unix/ext/process.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs index 6ab109cdb08c2..7830148b7e888 100644 --- a/library/std/src/sys/unix/ext/process.rs +++ b/library/std/src/sys/unix/ext/process.rs @@ -182,7 +182,7 @@ pub trait ExitStatusExt { /// If the process was stopped by a signal, returns that signal. /// - /// Ie, if `WIFSTOPPED`, this returns `WSTOPSIG`. This is only possible if the status came from + /// 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 = "none")] fn stopped_signal(&self) -> Option; From 06a405c49cfcdc091f1d84a3c6147d78fbdb5928 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sun, 13 Dec 2020 11:03:37 +0000 Subject: [PATCH 35/47] Replace `Ie` with `In other words` Co-authored-by: Joshua Nelson --- library/std/src/sys/unix/ext/process.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs index 7830148b7e888..a20f826e7f05a 100644 --- a/library/std/src/sys/unix/ext/process.rs +++ b/library/std/src/sys/unix/ext/process.rs @@ -172,7 +172,7 @@ pub trait ExitStatusExt { /// If the process was terminated by a signal, returns that signal. /// - /// Ie, if `WIFSIGNALED`, this returns `WTERMSIG`. + /// In other words, if `WIFSIGNALED`, this returns `WTERMSIG`. #[stable(feature = "rust1", since = "1.0.0")] fn signal(&self) -> Option; From fa68567a1fa87e92ad39b1749a134faedbbeae48 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 4 Jan 2021 17:37:34 +0000 Subject: [PATCH 36/47] unix ExitStatus: Add tracking issue to new methods Signed-off-by: Ian Jackson --- library/std/src/sys/unix/ext/process.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs index a20f826e7f05a..889382d3ed4ec 100644 --- a/library/std/src/sys/unix/ext/process.rs +++ b/library/std/src/sys/unix/ext/process.rs @@ -177,25 +177,25 @@ pub trait ExitStatusExt { fn signal(&self) -> Option; /// If the process was terminated by a signal, says whether it dumped core. - #[unstable(feature = "unix_process_wait_more", issue = "none")] + #[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 = "none")] + #[unstable(feature = "unix_process_wait_more", issue = "80695")] fn stopped_signal(&self) -> Option; /// 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 = "none")] + #[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 = "none")] + #[unstable(feature = "unix_process_wait_more", issue = "80695")] fn into_raw(self) -> i32; } From 70121941fffce3292e45b40c84d263af5bffb109 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 4 Jan 2021 17:11:41 +0000 Subject: [PATCH 37/47] ExitStatusExt unix: Retrospectively seal this trait As discussed in #79982. I think the "new interfaces", ie the new trait and impl, must be insta-stable. This seems OK because we are, in fact, adding a new restriction to the stable API. Signed-off-by: Ian Jackson --- library/std/src/sys/unix/ext/process.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs index 889382d3ed4ec..a72417818d066 100644 --- a/library/std/src/sys/unix/ext/process.rs +++ b/library/std/src/sys/unix/ext/process.rs @@ -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,8 +171,11 @@ impl CommandExt for process::Command { } /// Unix-specific extensions to [`process::ExitStatus`]. +/// +/// This trait is saeled (since Rust 1.51): 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")] @@ -199,6 +210,9 @@ pub trait ExitStatusExt { 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 { From f3e7199a79d23741e1fc6b0e58652d6de5f97fa0 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 4 Jan 2021 17:45:23 +0000 Subject: [PATCH 38/47] ExitStatusExt windows: Retrospectively seal this trait Signed-off-by: Ian Jackson --- library/std/src/sys/windows/ext/process.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/windows/ext/process.rs b/library/std/src/sys/windows/ext/process.rs index 61e4c6a1d1718..300385e966d37 100644 --- a/library/std/src/sys/windows/ext/process.rs +++ b/library/std/src/sys/windows/ext/process.rs @@ -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 saeled (since Rust 1.51): 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 { From efddf5949f36d68ff28abddb2c297c934d5b8eb5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 10 Jan 2021 18:11:00 -0800 Subject: [PATCH 39/47] Fix typo saeled -> sealed --- library/std/src/sys/unix/ext/process.rs | 2 +- library/std/src/sys/windows/ext/process.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs index a72417818d066..f4c67b225e6e1 100644 --- a/library/std/src/sys/unix/ext/process.rs +++ b/library/std/src/sys/unix/ext/process.rs @@ -172,7 +172,7 @@ impl CommandExt for process::Command { /// Unix-specific extensions to [`process::ExitStatus`]. /// -/// This trait is saeled (since Rust 1.51): it cannot be implemented outside the standard library. +/// 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: private::Sealed { diff --git a/library/std/src/sys/windows/ext/process.rs b/library/std/src/sys/windows/ext/process.rs index 300385e966d37..7a92381d6609b 100644 --- a/library/std/src/sys/windows/ext/process.rs +++ b/library/std/src/sys/windows/ext/process.rs @@ -82,7 +82,7 @@ impl IntoRawHandle for process::ChildStderr { /// Windows-specific extensions to [`process::ExitStatus`]. /// -/// This trait is saeled (since Rust 1.51): it cannot be implemented outside the standard library. +/// 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: private::Sealed { From 05a88aabc1bca6d06f5827bae9e8f448f5d39f28 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 13 Jan 2021 11:17:41 +0000 Subject: [PATCH 40/47] ExitStatusExt: Fix build on Fuchsia This is not particularly pretty but the current situation is a mess and I don't think I'm making it significantly worse. Signed-off-by: Ian Jackson --- .../src/sys/unix/process/process_fuchsia.rs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs index b64636c3f3d15..3102661b83dad 100644 --- a/library/std/src/sys/unix/process/process_fuchsia.rs +++ b/library/std/src/sys/unix/process/process_fuchsia.rs @@ -245,6 +245,50 @@ impl ExitStatus { pub fn signal(&self) -> Option { 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 bdoge. 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 { + 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 covert 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. From b59fa3d6343d560d5b5bde65c76d8a4ea4c27949 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 13 Jan 2021 14:21:18 +0000 Subject: [PATCH 41/47] Fix stabilisation version of slice_strip See https://github.com/rust-lang/rust/pull/77853#pullrequestreview-564921079 Signed-off-by: Ian Jackson --- library/core/src/slice/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 081d80f487605..6de2714059480 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1877,7 +1877,7 @@ impl [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 + ?Sized>(&self, prefix: &P) -> Option<&[T]> where T: PartialEq, @@ -1911,7 +1911,7 @@ impl [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 + ?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 SlicePattern for [T] { type Item = T; @@ -3333,7 +3333,7 @@ impl SlicePattern for [T] { } } -#[stable(feature = "slice_strip", since = "1.50.0")] +#[stable(feature = "slice_strip", since = "1.51.0")] impl SlicePattern for [T; N] { type Item = T; From 95289889fe4b9a69abe2963974e2df7c9a065927 Mon Sep 17 00:00:00 2001 From: Lukas Lueg Date: Wed, 13 Jan 2021 19:47:41 +0100 Subject: [PATCH 42/47] Add doc intralinks --- library/core/src/iter/adapters/intersperse.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index 9f5cca88206ef..25115beb85129 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -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 it's documentation +/// for more information. #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] #[derive(Debug, Clone)] pub struct Intersperse @@ -55,6 +58,9 @@ where } /// An iterator adapter that places a separator between all elements. +/// +/// This `struct` is created by [`Iterator::intersperse_with`]. See it's +/// documentation for more information. #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] pub struct IntersperseWith where From 0342fd16ffb146c849f1bb40d42ba1bb7a940b62 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 13 Jan 2021 11:55:49 -0800 Subject: [PATCH 43/47] Remove the unused context from CreateDebugLocation This went unused in commit 88d874de6395, part of #68965. --- compiler/rustc_codegen_llvm/src/debuginfo/mod.rs | 1 - compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 - compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 6 ++---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index ccbe7325cc6c2..955e739b2c126 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -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, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index e359d9f8c9c77..eb4f36266dbae 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2102,7 +2102,6 @@ extern "C" { ); pub fn LLVMRustDIBuilderCreateDebugLocation( - Context: &'a Context, Line: c_uint, Column: c_uint, Scope: &'a DIScope, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index c0ff62c17beb5..1d6f00562f136 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -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(Scope), unwrapDIPtr(InlinedAt)); From 391b4cc3789b7585affc1bae8189900a36110c5e Mon Sep 17 00:00:00 2001 From: Caleb Sander Date: Wed, 13 Jan 2021 15:05:39 -0500 Subject: [PATCH 44/47] Fix formatting specifiers doc link Was incorrectly linked to `core::fmt`, which is empty, in d36e3e23a80f039ee98117ebba0bb2ea6e34f0c1 Some of the links were fixed already in 3baf6a4a749bd6ac4a8b9f1054d3f2ad2fc91e45 --- library/core/src/fmt/mod.rs | 36 +++++++++++++++++++++++++--------- library/core/src/macros/mod.rs | 6 +++--- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 0c65c1c9eb7e9..a76248204422d 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -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 /// diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 1634aff7b4dc9..90964bae98c89 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -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 /// From 9b2f085110c70a8ae92a47ce0c510db82f759992 Mon Sep 17 00:00:00 2001 From: Lukas Lueg Date: Wed, 13 Jan 2021 21:07:59 +0100 Subject: [PATCH 45/47] Improve Iterator::intersperse_ docs --- library/core/src/iter/adapters/intersperse.rs | 4 ++-- library/core/src/iter/traits/iterator.rs | 20 +++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index 25115beb85129..1d01e9b5fb7dc 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -2,7 +2,7 @@ use super::Peekable; /// An iterator adapter that places a separator between all elements. /// -/// This `struct` is created by [`Iterator::intersperse`]. See it's documentation +/// 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)] @@ -59,7 +59,7 @@ where /// An iterator adapter that places a separator between all elements. /// -/// This `struct` is created by [`Iterator::intersperse_with`]. See it's +/// 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 diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 91d7a47907a46..732d465fcaeb3 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -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::(); - /// assert_eq!(hello, "Hello World"); + /// let hello = ["Hello", "World", "!"].iter().copied().intersperse(" ").collect::(); + /// 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 @@ -600,11 +606,13 @@ pub trait Iterator { /// ``` /// #![feature(iter_intersperse)] /// - /// let src = ["Hello", "to", "all", "people"].iter().copied(); - /// let mut separator = [" ❤️ ", " 😀 "].iter().copied().cycle(); + /// 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.next().unwrap()).collect::(); - /// assert_eq!(result, "Hello ❤️ to 😀 all ❤️ people"); + /// let result = src.intersperse_with(separator).collect::(); + /// assert_eq!(result, "Hello ❤️ to 😀 all 🦀 people 🦀 !!"); /// ``` #[inline] #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] From eb72dc5d40767f9267e0e42dc1139f7976a0abd1 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 28 Dec 2020 11:41:52 -0500 Subject: [PATCH 46/47] Add as_ref and as_mut methods for Bound Add as_ref and as_mut method for std::ops::range::Bound, patterned off of the methods of the same name on Option. --- library/core/src/ops/range.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 1d67e65e51f5f..0571dc74b9af9 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -678,6 +678,29 @@ pub enum Bound { Unbounded, } +#[unstable(feature = "bound_as_ref", issue = "80996")] +impl Bound { + /// Converts from `&Bound` 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` 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 Bound<&T> { /// Map a `Bound<&T>` to a `Bound` by cloning the contents of the bound. /// From a8d01619608715e6abc4c6d3c6f347f393262725 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 13 Jan 2021 22:13:45 -0800 Subject: [PATCH 47/47] Fix typos in Fuchsia unix_process_wait_more --- library/std/src/sys/unix/process/process_fuchsia.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs index 3102661b83dad..0d4703d7f503a 100644 --- a/library/std/src/sys/unix/process/process_fuchsia.rs +++ b/library/std/src/sys/unix/process/process_fuchsia.rs @@ -251,7 +251,7 @@ impl ExitStatus { // 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 bdoge. So + // 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 { @@ -285,7 +285,7 @@ impl ExitStatus { // 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 covert the value into a traditional Unix-style wait status, which cannot represent values greater than 255."); + 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 }