From 4f5563d0275118cbebbc2a3d3d60be1a7600adaa Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Thu, 9 Sep 2021 16:58:41 +0200 Subject: [PATCH 01/22] Added abs_diff for integer types. --- library/core/src/num/int_macros.rs | 40 +++++++++++++++++++++++++++++ library/core/src/num/uint_macros.rs | 21 +++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 2a02545041dcf..187be5d47573a 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2227,6 +2227,46 @@ macro_rules! int_impl { } } + /// Computes the absolute difference between `self` and `other`. + /// + /// This function always returns the correct answer without overflow or + /// panics by returning an unsigned integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(int_abs_diff)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(80), 20", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(110), 10", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").abs_diff(80), 180", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").abs_diff(-120), 20", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.abs_diff(", stringify!($SelfT), "::MAX), ", stringify!($UnsignedT), "::MAX);")] + /// ``` + #[unstable(feature = "int_abs_diff", issue = "none")] + #[inline] + pub const fn abs_diff(self, other: Self) -> $UnsignedT { + if self < other { + // Converting a non-negative x from signed to unsigned by using + // `x as U` is left unchanged, but a negative x is converted + // to value x + 2^N. Thus if `s` and `o` are binary variables + // respectively indicating whether `self` and `other` are + // negative, we are computing the mathematical value: + // + // (other + o*2^N) - (self + s*2^N) mod 2^N + // other - self + (o-s)*2^N mod 2^N + // other - self mod 2^N + // + // Finally, taking the mod 2^N of the mathematical value of + // `other - self` does not change it as it already is + // in the range [0, 2^N). + (other as $UnsignedT).wrapping_sub(self as $UnsignedT) + } else { + (self as $UnsignedT).wrapping_sub(other as $UnsignedT) + } + } + /// Returns a number representing sign of `self`. /// /// - `0` if the number is zero diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 7523d8ec976dd..1bba4179f9955 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1490,6 +1490,27 @@ macro_rules! uint_impl { (c, b | d) } + /// Computes the absolute difference between `self` and `other`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(int_abs_diff)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(80), 20", stringify!($SelfT), ");")] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(110), 10", stringify!($SelfT), ");")] + /// ``` + #[unstable(feature = "int_abs_diff", issue = "none")] + #[inline] + pub const fn abs_diff(self, other: Self) -> Self { + if self < other { + other - self + } else { + self - other + } + } + /// Calculates the multiplication of `self` and `rhs`. /// /// Returns a tuple of the multiplication along with a boolean From 77e7f8ae88910d64ebeba5689e90d7c1a01f2bf3 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Thu, 9 Sep 2021 23:01:28 +0200 Subject: [PATCH 02/22] Added psadbw support for u8::abs_diff. --- library/core/src/num/uint_macros.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 1bba4179f9955..a5f12447fdc32 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1504,10 +1504,16 @@ macro_rules! uint_impl { #[unstable(feature = "int_abs_diff", issue = "none")] #[inline] pub const fn abs_diff(self, other: Self) -> Self { - if self < other { - other - self + if mem::size_of::() == 1 { + // Trick LLVM into generating the psadbw instruction when SSE2 + // is available and this function is autovectorized for u8's. + (self as i32).wrapping_sub(other as i32).abs() as Self } else { - self - other + if self < other { + other - self + } else { + self - other + } } } From d8dae4f8e51d3085664cf5035b0c7d9c237207c8 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 16 Aug 2021 20:53:40 +0100 Subject: [PATCH 03/22] Perform type inference in range pattern --- compiler/rustc_typeck/src/check/pat.rs | 59 ++++++++++++++----- .../ui/pattern/patkind-litrange-no-expr.rs | 1 - .../pattern/patkind-litrange-no-expr.stderr | 12 +--- 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 140a9d1126d32..45b630f35ccc5 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -448,16 +448,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ti: TopInfo<'tcx>, ) -> Ty<'tcx> { let calc_side = |opt_expr: Option<&'tcx hir::Expr<'tcx>>| match opt_expr { - None => (None, None), + None => None, Some(expr) => { let ty = self.check_expr(expr); - // Check that the end-point is of numeric or char type. - let fail = !(ty.is_numeric() || ty.is_char() || ty.references_error()); - (Some(ty), Some((fail, ty, expr.span))) + // Check that the end-point is possibly of numeric or char type. + // The early check here is not for correctness, but rather better + // diagnostics (e.g. when `&str` is being matched, `expected` will + // be peeled to `str` while ty here is still `&str`, if we don't + // err ealy here, a rather confusing unification error will be + // emitted instead). + let fail = + !(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error()); + Some((fail, ty, expr.span)) } }; - let (lhs_ty, lhs) = calc_side(lhs); - let (rhs_ty, rhs) = calc_side(rhs); + let mut lhs = calc_side(lhs); + let mut rhs = calc_side(rhs); if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) { // There exists a side that didn't meet our criteria that the end-point @@ -466,25 +472,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return self.tcx.ty_error(); } - // Now that we know the types can be unified we find the unified type - // and use it to type the entire expression. - let common_type = self.resolve_vars_if_possible(lhs_ty.or(rhs_ty).unwrap_or(expected)); - + // Unify each side with `expected`. // Subtyping doesn't matter here, as the value is some kind of scalar. - let demand_eqtype = |x, y| { - if let Some((_, x_ty, x_span)) = x { + let demand_eqtype = |x: &mut _, y| { + if let Some((ref mut fail, x_ty, x_span)) = *x { if let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti) { if let Some((_, y_ty, y_span)) = y { self.endpoint_has_type(&mut err, y_span, y_ty); } err.emit(); + *fail = true; }; } }; - demand_eqtype(lhs, rhs); - demand_eqtype(rhs, lhs); + demand_eqtype(&mut lhs, rhs); + demand_eqtype(&mut rhs, lhs); + + if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) { + return self.tcx.ty_error(); + } - common_type + // Find the unified type and check if it's of numeric or char type again. + // This check is needed if both sides are inference variables. + // We require types to be resolved here so that we emit inference failure + // rather than "_ is not a char or numeric". + let ty = self.structurally_resolved_type(span, expected); + if !(ty.is_numeric() || ty.is_char() || ty.references_error()) { + if let Some((ref mut fail, _, _)) = lhs { + *fail = true; + } + if let Some((ref mut fail, _, _)) = rhs { + *fail = true; + } + self.emit_err_pat_range(span, lhs, rhs); + return self.tcx.ty_error(); + } + ty } fn endpoint_has_type(&self, err: &mut DiagnosticBuilder<'_>, span: Span, ty: Ty<'_>) { @@ -511,10 +534,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { E0029, "only `char` and numeric types are allowed in range patterns" ); - let msg = |ty| format!("this is of type `{}` but it should be `char` or numeric", ty); + let msg = |ty| { + let ty = self.resolve_vars_if_possible(ty); + format!("this is of type `{}` but it should be `char` or numeric", ty) + }; let mut one_side_err = |first_span, first_ty, second: Option<(bool, Ty<'tcx>, Span)>| { err.span_label(first_span, &msg(first_ty)); if let Some((_, ty, sp)) = second { + let ty = self.resolve_vars_if_possible(ty); self.endpoint_has_type(&mut err, sp, ty); } }; diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.rs b/src/test/ui/pattern/patkind-litrange-no-expr.rs index 9464f277fb088..7ef541cb58528 100644 --- a/src/test/ui/pattern/patkind-litrange-no-expr.rs +++ b/src/test/ui/pattern/patkind-litrange-no-expr.rs @@ -19,7 +19,6 @@ enum_number!(Change { Neg = -1, Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns //~| ERROR arbitrary expressions aren't allowed in patterns - //~| ERROR only `char` and numeric types are allowed in range patterns }); fn main() {} diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.stderr b/src/test/ui/pattern/patkind-litrange-no-expr.stderr index 51af167a7c1d1..eb1ee7e45673d 100644 --- a/src/test/ui/pattern/patkind-litrange-no-expr.stderr +++ b/src/test/ui/pattern/patkind-litrange-no-expr.stderr @@ -10,15 +10,5 @@ error: arbitrary expressions aren't allowed in patterns LL | Arith = 1 + 1, | ^^^^^ -error[E0029]: only `char` and numeric types are allowed in range patterns - --> $DIR/patkind-litrange-no-expr.rs:20:13 - | -LL | $( $value ..= 42 => Some($name::$variant), )* // PatKind::Range - | -- this is of type `{integer}` -... -LL | Arith = 1 + 1, - | ^^^^^ this is of type `_` but it should be `char` or numeric - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0029`. From ca1616c75b64bf7edebefcc70be010e5ac736c97 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 16 Aug 2021 21:00:17 +0100 Subject: [PATCH 04/22] Add ui test for issue 88074 --- .../issue-88074-pat-range-type-inference.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/test/ui/pattern/issue-88074-pat-range-type-inference.rs diff --git a/src/test/ui/pattern/issue-88074-pat-range-type-inference.rs b/src/test/ui/pattern/issue-88074-pat-range-type-inference.rs new file mode 100644 index 0000000000000..27db7d8c7ab9d --- /dev/null +++ b/src/test/ui/pattern/issue-88074-pat-range-type-inference.rs @@ -0,0 +1,16 @@ +// check-pass + +trait Zero { + const ZERO: Self; +} + +impl Zero for i32 { + const ZERO: Self = 0; +} + +fn main() { + match 1 { + Zero::ZERO ..= 1 => {}, + _ => {}, + } +} From 52a040379010f78a75ffc4806c968b3489372311 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 16 Aug 2021 21:23:48 +0100 Subject: [PATCH 05/22] Add a range pattern inference failing test --- ...ssue-88074-pat-range-type-inference-err.rs | 28 +++++++++++++++++++ ...-88074-pat-range-type-inference-err.stderr | 21 ++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/test/ui/pattern/issue-88074-pat-range-type-inference-err.rs create mode 100644 src/test/ui/pattern/issue-88074-pat-range-type-inference-err.stderr diff --git a/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.rs b/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.rs new file mode 100644 index 0000000000000..16df272df6bd9 --- /dev/null +++ b/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.rs @@ -0,0 +1,28 @@ +trait Zero { + const ZERO: Self; +} + +impl Zero for String { + const ZERO: Self = String::new(); +} + +fn foo() { + match String::new() { + Zero::ZERO ..= Zero::ZERO => {}, + //~^ ERROR only `char` and numeric types are allowed in range patterns + _ => {}, + } +} + +fn bar() { + match Zero::ZERO { + Zero::ZERO ..= Zero::ZERO => {}, + //~^ ERROR type annotations needed [E0282] + _ => {}, + } +} + +fn main() { + foo(); + bar(); +} diff --git a/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.stderr b/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.stderr new file mode 100644 index 0000000000000..06a279925edbc --- /dev/null +++ b/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.stderr @@ -0,0 +1,21 @@ +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/issue-88074-pat-range-type-inference-err.rs:11:9 + | +LL | Zero::ZERO ..= Zero::ZERO => {}, + | ----------^^^^^---------- + | | | + | | this is of type `String` but it should be `char` or numeric + | this is of type `String` but it should be `char` or numeric + +error[E0282]: type annotations needed + --> $DIR/issue-88074-pat-range-type-inference-err.rs:19:9 + | +LL | Zero::ZERO ..= Zero::ZERO => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + | + = note: type must be known at this point + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0029, E0282. +For more information about an error, try `rustc --explain E0029`. From c8f86cad2dda3181bfedc165d3dd4bf452770228 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 30 Sep 2021 21:42:09 +0100 Subject: [PATCH 06/22] Elaborate predicates in min_specialization checks Supertraits of specialization markers could circumvent checks for min_specialization. Elaborating predicates prevents this. --- .../rustc_trait_selection/src/traits/mod.rs | 4 +- .../src/impl_wf_check/min_specialization.rs | 48 ++++++++++++------- .../spec-marker-supertraits.rs | 29 +++++++++++ .../spec-marker-supertraits.stderr | 13 +++++ 4 files changed, 76 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/specialization/min_specialization/spec-marker-supertraits.rs create mode 100644 src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index b3c9cf4c173ec..d777f586e23c5 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -64,7 +64,9 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; pub use self::specialize::{specialization_graph, translate_substs, OverlapError}; pub use self::structural_match::search_for_structural_match_violation; pub use self::structural_match::NonStructuralMatchTy; -pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; +pub use self::util::{ + elaborate_obligations, elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs, +}; pub use self::util::{expand_trait_aliases, TraitAliasExpander}; pub use self::util::{ get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices, diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index 8ecd6034ad695..f4bb5761c19bd 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -74,7 +74,7 @@ use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt}; use rustc_infer::traits::specialization_graph::Node; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use rustc_middle::ty::trait_def::TraitSpecializationKind; -use rustc_middle::ty::{self, InstantiatedPredicates, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_span::Span; use rustc_trait_selection::traits::{self, translate_substs, wf}; @@ -294,13 +294,27 @@ fn check_predicates<'tcx>( span: Span, ) { let tcx = infcx.tcx; - let impl1_predicates = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); + let impl1_predicates: Vec<_> = traits::elaborate_predicates( + tcx, + tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).predicates.into_iter(), + ) + .map(|obligation| obligation.predicate) + .collect(); + let mut impl2_predicates = if impl2_node.is_from_trait() { // Always applicable traits have to be always applicable without any // assumptions. - InstantiatedPredicates::empty() + Vec::new() } else { - tcx.predicates_of(impl2_node.def_id()).instantiate(tcx, impl2_substs) + traits::elaborate_predicates( + tcx, + tcx.predicates_of(impl2_node.def_id()) + .instantiate(tcx, impl2_substs) + .predicates + .into_iter(), + ) + .map(|obligation| obligation.predicate) + .collect() }; debug!( "check_always_applicable(\nimpl1_predicates={:?},\nimpl2_predicates={:?}\n)", @@ -322,13 +336,12 @@ fn check_predicates<'tcx>( // which is sound because we forbid impls like the following // // impl AlwaysApplicable for D { } - let always_applicable_traits = - impl1_predicates.predicates.iter().copied().filter(|&predicate| { - matches!( - trait_predicate_kind(tcx, predicate), - Some(TraitSpecializationKind::AlwaysApplicable) - ) - }); + let always_applicable_traits = impl1_predicates.iter().copied().filter(|&predicate| { + matches!( + trait_predicate_kind(tcx, predicate), + Some(TraitSpecializationKind::AlwaysApplicable) + ) + }); // Include the well-formed predicates of the type parameters of the impl. for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().substs { @@ -340,18 +353,19 @@ fn check_predicates<'tcx>( arg, span, ) { - impl2_predicates - .predicates - .extend(obligations.into_iter().map(|obligation| obligation.predicate)) + impl2_predicates.extend( + traits::elaborate_obligations(tcx, obligations) + .map(|obligation| obligation.predicate), + ) } } - impl2_predicates.predicates.extend( + impl2_predicates.extend( traits::elaborate_predicates(tcx, always_applicable_traits) .map(|obligation| obligation.predicate), ); - for predicate in impl1_predicates.predicates { - if !impl2_predicates.predicates.contains(&predicate) { + for predicate in impl1_predicates { + if !impl2_predicates.contains(&predicate) { check_specialization_on(tcx, predicate, span) } } diff --git a/src/test/ui/specialization/min_specialization/spec-marker-supertraits.rs b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.rs new file mode 100644 index 0000000000000..3bb2480e9e2be --- /dev/null +++ b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.rs @@ -0,0 +1,29 @@ +// Check that supertraits cannot be used to work around min_specialization +// limitations. + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +trait HasMethod { + fn method(&self); +} + +#[rustc_unsafe_specialization_marker] +trait Marker: HasMethod {} + +trait Spec { + fn spec_me(&self); +} + +impl Spec for T { + default fn spec_me(&self) {} +} + +impl Spec for T { + //~^ ERROR cannot specialize on trait `HasMethod` + fn spec_me(&self) { + self.method(); + } +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr new file mode 100644 index 0000000000000..964109dd10f47 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr @@ -0,0 +1,13 @@ +error: cannot specialize on trait `HasMethod` + --> $DIR/spec-marker-supertraits.rs:22:1 + | +LL | / impl Spec for T { +LL | | +LL | | fn spec_me(&self) { +LL | | self.method(); +LL | | } +LL | | } + | |_^ + +error: aborting due to previous error + From 051d5b0118186433cdb1e12c6198b877bfa0a8fc Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 30 Sep 2021 21:42:41 +0100 Subject: [PATCH 07/22] Fix standard library for min_specialization changes --- library/alloc/src/vec/into_iter.rs | 13 ++++++++++--- library/alloc/src/vec/source_iter_marker.rs | 16 +++------------- library/core/src/iter/adapters/enumerate.rs | 8 ++++---- library/core/src/iter/adapters/filter.rs | 9 ++++----- library/core/src/iter/adapters/filter_map.rs | 9 ++++----- library/core/src/iter/adapters/inspect.rs | 9 ++++----- library/core/src/iter/adapters/map.rs | 9 ++++----- library/core/src/iter/adapters/map_while.rs | 9 ++++----- library/core/src/iter/adapters/mod.rs | 11 ++++++----- library/core/src/iter/adapters/peekable.rs | 8 ++++---- library/core/src/iter/adapters/scan.rs | 9 ++++----- library/core/src/iter/adapters/skip.rs | 8 ++++---- library/core/src/iter/adapters/skip_while.rs | 9 ++++----- library/core/src/iter/adapters/take.rs | 8 ++++---- library/core/src/iter/adapters/take_while.rs | 9 ++++----- library/core/src/iter/adapters/zip.rs | 10 ++++------ 16 files changed, 71 insertions(+), 83 deletions(-) diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 4cb0a4b10bd0c..096262b41d717 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -220,14 +220,21 @@ unsafe impl TrustedLen for IntoIter {} #[doc(hidden)] #[unstable(issue = "none", feature = "std_internals")] +#[rustc_unsafe_specialization_marker] +pub trait NonDrop {} + // T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr // and thus we can't implement drop-handling -// +#[unstable(issue = "none", feature = "std_internals")] +impl NonDrop for T {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "std_internals")] // TrustedRandomAccess (without NoCoerce) must not be implemented because -// subtypes/supertypes of `T` might not be `Copy` +// subtypes/supertypes of `T` might not be `NonDrop` unsafe impl TrustedRandomAccessNoCoerce for IntoIter where - T: Copy, + T: NonDrop, { const MAY_HAVE_SIDE_EFFECT: bool = false; } diff --git a/library/alloc/src/vec/source_iter_marker.rs b/library/alloc/src/vec/source_iter_marker.rs index e05788d99c0df..6e78534cf5b10 100644 --- a/library/alloc/src/vec/source_iter_marker.rs +++ b/library/alloc/src/vec/source_iter_marker.rs @@ -6,24 +6,14 @@ use super::{AsIntoIter, InPlaceDrop, SpecFromIter, SpecFromIterNested, Vec}; /// Specialization marker for collecting an iterator pipeline into a Vec while reusing the /// source allocation, i.e. executing the pipeline in place. -/// -/// The SourceIter parent trait is necessary for the specializing function to access the allocation -/// which is to be reused. But it is not sufficient for the specialization to be valid. See -/// additional bounds on the impl. #[rustc_unsafe_specialization_marker] -pub(super) trait SourceIterMarker: SourceIter {} +pub(super) trait InPlaceIterableMarker {} -// The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of -// Adapter>> (all owned by core/std). Additional bounds -// on the adapter implementations (beyond `impl Trait for Adapter`) only depend on other -// traits already marked as specialization traits (Copy, TrustedRandomAccess, FusedIterator). -// I.e. the marker does not depend on lifetimes of user-supplied types. Modulo the Copy hole, which -// several other specializations already depend on. -impl SourceIterMarker for T where T: SourceIter + InPlaceIterable {} +impl InPlaceIterableMarker for T where T: InPlaceIterable {} impl SpecFromIter for Vec where - I: Iterator + SourceIterMarker, + I: Iterator + SourceIter + InPlaceIterableMarker, { default fn from_iter(mut iterator: I) -> Self { // Additional requirements which cannot expressed via trait bounds. We rely on const eval diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index 3478a0cd40832..f0143cf0c3d0f 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -227,14 +227,14 @@ impl FusedIterator for Enumerate where I: FusedIterator {} unsafe impl TrustedLen for Enumerate where I: TrustedLen {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Enumerate +unsafe impl SourceIter for Enumerate where - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs index d5f19f127470e..a0afaa326ad63 100644 --- a/library/core/src/iter/adapters/filter.rs +++ b/library/core/src/iter/adapters/filter.rs @@ -135,15 +135,14 @@ where impl FusedIterator for Filter where P: FnMut(&I::Item) -> bool {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Filter +unsafe impl SourceIter for Filter where - P: FnMut(&I::Item) -> bool, - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs index 01b7be9d52daf..e0d665c9e12ba 100644 --- a/library/core/src/iter/adapters/filter_map.rs +++ b/library/core/src/iter/adapters/filter_map.rs @@ -129,15 +129,14 @@ where impl FusedIterator for FilterMap where F: FnMut(I::Item) -> Option {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for FilterMap +unsafe impl SourceIter for FilterMap where - F: FnMut(I::Item) -> Option, - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/inspect.rs b/library/core/src/iter/adapters/inspect.rs index 36835d12e5685..19839fdfe5bc3 100644 --- a/library/core/src/iter/adapters/inspect.rs +++ b/library/core/src/iter/adapters/inspect.rs @@ -149,15 +149,14 @@ where impl FusedIterator for Inspect where F: FnMut(&I::Item) {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Inspect +unsafe impl SourceIter for Inspect where - F: FnMut(&I::Item), - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index 763e253e75a51..449650a22f435 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -201,15 +201,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Map +unsafe impl SourceIter for Map where - F: FnMut(I::Item) -> B, - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs index 793b05fcf9529..1e8d6bf3e00e1 100644 --- a/library/core/src/iter/adapters/map_while.rs +++ b/library/core/src/iter/adapters/map_while.rs @@ -80,15 +80,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for MapWhile +unsafe impl SourceIter for MapWhile where - P: FnMut(I::Item) -> Option, - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 48e7dcfa7d9a3..1e1ce866ff3f2 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -92,9 +92,10 @@ pub use self::zip::zip; /// [`as_inner`]: SourceIter::as_inner #[unstable(issue = "none", feature = "inplace_iteration")] #[doc(hidden)] +#[rustc_specialization_trait] pub unsafe trait SourceIter { /// A source stage in an iterator pipeline. - type Source: Iterator; + type Source; /// Retrieve the source of an iterator pipeline. /// @@ -200,14 +201,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for ResultShunt<'_, I, E> +unsafe impl SourceIter for ResultShunt<'_, I, E> where - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut Self::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 91fa1a9ad351c..20aca323bab79 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -321,14 +321,14 @@ impl Peekable { unsafe impl TrustedLen for Peekable where I: TrustedLen {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Peekable +unsafe impl SourceIter for Peekable where - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs index 96705b01f661f..80bfd2231241b 100644 --- a/library/core/src/iter/adapters/scan.rs +++ b/library/core/src/iter/adapters/scan.rs @@ -90,15 +90,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Scan +unsafe impl SourceIter for Scan where - I: SourceIter, - F: FnMut(&mut St, I::Item) -> Option, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs index c358a6d12b7bc..bb3480008700a 100644 --- a/library/core/src/iter/adapters/skip.rs +++ b/library/core/src/iter/adapters/skip.rs @@ -180,14 +180,14 @@ where impl FusedIterator for Skip where I: FusedIterator {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Skip +unsafe impl SourceIter for Skip where - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/skip_while.rs b/library/core/src/iter/adapters/skip_while.rs index 93e29edc8df39..f29661779c056 100644 --- a/library/core/src/iter/adapters/skip_while.rs +++ b/library/core/src/iter/adapters/skip_while.rs @@ -105,15 +105,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for SkipWhile +unsafe impl SourceIter for SkipWhile where - P: FnMut(&I::Item) -> bool, - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index beda8c32c6bdc..38d43e070b64f 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -114,14 +114,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Take +unsafe impl SourceIter for Take where - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs index 93457d20f7c23..ded216da952a3 100644 --- a/library/core/src/iter/adapters/take_while.rs +++ b/library/core/src/iter/adapters/take_while.rs @@ -118,15 +118,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for TakeWhile +unsafe impl SourceIter for TakeWhile where - P: FnMut(&I::Item) -> bool, - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 17697fa0e045a..2b7287a413376 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -414,16 +414,14 @@ where // Arbitrarily selects the left side of the zip iteration as extractable "source" // it would require negative trait bounds to be able to try both #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Zip +unsafe impl SourceIter for Zip where - A: SourceIter, - B: Iterator, - S: Iterator, + A: SourceIter, { - type Source = S; + type Source = A::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut A::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.a) } } From fa4072f7d32221adf5edc8d57c9cb8fef3ddc96e Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sun, 26 Sep 2021 14:21:22 +0100 Subject: [PATCH 08/22] path.push() should work as expected on windows verbatim paths --- library/std/src/path.rs | 53 ++++++++++++++++++++++++++++++----- library/std/src/path/tests.rs | 9 ++++++ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 9d5778ed48cfe..a45ecf6ea8c63 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1231,20 +1231,59 @@ impl PathBuf { let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false); // in the special case of `C:` on Windows, do *not* add a separator + let comps = self.components(); + + if comps.prefix_len() > 0 + && comps.prefix_len() == comps.path.len() + && comps.prefix.unwrap().is_drive() { - let comps = self.components(); - if comps.prefix_len() > 0 - && comps.prefix_len() == comps.path.len() - && comps.prefix.unwrap().is_drive() - { - need_sep = false - } + need_sep = false } // absolute `path` replaces `self` if path.is_absolute() || path.prefix().is_some() { self.as_mut_vec().truncate(0); + // verbatim paths need . and .. removed + } else if comps.prefix_verbatim() { + let mut buf: Vec<_> = comps.collect(); + for c in path.components() { + match c { + Component::RootDir => { + buf.truncate(1); + buf.push(c); + } + Component::CurDir => (), + Component::ParentDir => { + if let Some(Component::Normal(_)) = buf.last() { + buf.pop(); + } + } + _ => buf.push(c), + } + } + + let mut res = OsString::new(); + let mut need_sep = false; + + for c in buf { + if need_sep && c != Component::RootDir { + res.push(MAIN_SEP_STR); + } + res.push(c.as_os_str()); + + need_sep = match c { + Component::RootDir => false, + Component::Prefix(prefix) => { + !prefix.parsed.is_drive() && prefix.parsed.len() > 0 + } + _ => true, + } + } + + self.inner = res; + return; + // `path` has a root but no prefix, e.g., `\windows` (Windows only) } else if path.has_root() { let prefix_len = self.components().prefix_remaining(); diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index ce23cf6cd21b9..3973a6829d3d3 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -1262,6 +1262,15 @@ pub fn test_push() { tp!("\\\\.\\foo", "..\\bar", "\\\\.\\foo\\..\\bar"); tp!("\\\\?\\C:", "foo", "\\\\?\\C:\\foo"); // this is a weird one + + tp!(r"\\?\C:\bar", "../foo", r"\\?\C:\foo"); + tp!(r"\\?\C:\bar", "../../foo", r"\\?\C:\foo"); + tp!(r"\\?\C:\", "../foo", r"\\?\C:\foo"); + tp!(r"\\?\C:", r"D:\foo/./", r"D:\foo/./"); + tp!(r"\\?\C:", r"\\?\D:\foo\.\", r"\\?\D:\foo\.\"); + tp!(r"\\?\A:\x\y", "/foo", r"\\?\A:\foo"); + tp!(r"\\?\A:", r"..\foo\.", r"\\?\A:\foo"); + tp!(r"\\?\A:\x\y", r".\foo\.", r"\\?\A:\x\y\foo"); } } From 03cf07f85ff365c4b9f4fd048252bfd0d3334325 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 1 Oct 2021 20:51:38 -0700 Subject: [PATCH 09/22] Update to the final LLVM 13.0.0 release --- .gitmodules | 2 +- src/llvm-project | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index e22d576279042..c60a0dd2c7c43 100644 --- a/.gitmodules +++ b/.gitmodules @@ -34,7 +34,7 @@ [submodule "src/llvm-project"] path = src/llvm-project url = https://github.com/rust-lang/llvm-project.git - branch = rustc/13.0-2021-08-08 + branch = rustc/13.0-2021-09-30 [submodule "src/doc/embedded-book"] path = src/doc/embedded-book url = https://github.com/rust-embedded/book.git diff --git a/src/llvm-project b/src/llvm-project index 522c3e3d9c097..a7348ae0df3c7 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 522c3e3d9c097b53ede7682cc28544b461597b20 +Subproject commit a7348ae0df3c71581dbe3d355fc0fb6ce6332dd0 From e2d3e09b9cb60f148e99d16e9af650f81275e5f1 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 30 May 2021 16:45:51 +0200 Subject: [PATCH 10/22] Prevent macro ambiguity errors The previous macro_rules! parsers failed when an additional modifier was added with ambiguity errors. The error is pretty unclear as to what exactly the cause here is, but this change simplifies the argument parsing code such that the error is avoided. --- compiler/rustc_macros/src/query.rs | 12 ++++----- .../rustc_middle/src/dep_graph/dep_node.rs | 4 +-- compiler/rustc_middle/src/ty/query.rs | 6 ++--- compiler/rustc_query_impl/src/plumbing.rs | 26 +++++++++---------- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 7ad36973f46c7..005017185c148 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -455,28 +455,28 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { // Pass on the fatal_cycle modifier if let Some(fatal_cycle) = &modifiers.fatal_cycle { - attributes.push(quote! { #fatal_cycle }); + attributes.push(quote! { (#fatal_cycle) }); }; // Pass on the storage modifier if let Some(ref ty) = modifiers.storage { let span = ty.span(); - attributes.push(quote_spanned! {span=> storage(#ty) }); + attributes.push(quote_spanned! {span=> (storage #ty) }); }; // Pass on the cycle_delay_bug modifier if let Some(cycle_delay_bug) = &modifiers.cycle_delay_bug { - attributes.push(quote! { #cycle_delay_bug }); + attributes.push(quote! { (#cycle_delay_bug) }); }; // Pass on the no_hash modifier if let Some(no_hash) = &modifiers.no_hash { - attributes.push(quote! { #no_hash }); + attributes.push(quote! { (#no_hash) }); }; // Pass on the anon modifier if let Some(anon) = &modifiers.anon { - attributes.push(quote! { #anon }); + attributes.push(quote! { (#anon) }); }; // Pass on the eval_always modifier if let Some(eval_always) = &modifiers.eval_always { - attributes.push(quote! { #eval_always }); + attributes.push(quote! { (#eval_always) }); }; // This uses the span of the query definition for the commas, diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index e788dd4be85d7..07d42902be5dd 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -140,11 +140,11 @@ macro_rules! is_eval_always_attr { } macro_rules! contains_anon_attr { - ($($attr:ident $(($($attr_args:tt)*))* ),*) => ({$(is_anon_attr!($attr) | )* false}); + ($(($attr:ident $($attr_args:tt)* )),*) => ({$(is_anon_attr!($attr) | )* false}); } macro_rules! contains_eval_always_attr { - ($($attr:ident $(($($attr_args:tt)*))* ),*) => ({$(is_eval_always_attr!($attr) | )* false}); + ($(($attr:ident $($attr_args:tt)* )),*) => ({$(is_eval_always_attr!($attr) | )* false}); } #[allow(non_upper_case_globals)] diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 154b26464a804..e5fd38252da53 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -111,11 +111,11 @@ macro_rules! query_storage { ([][$K:ty, $V:ty]) => { >::Cache }; - ([storage($ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => { + ([(storage $ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => { <$ty as CacheSelector<$K, $V>>::Cache }; - ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => { - query_storage!([$($($modifiers)*)*][$($args)*]) + ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { + query_storage!([$($modifiers)*][$($args)*]) }; } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index bb686b5ef3f3a..818b798ab55e7 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -253,17 +253,17 @@ macro_rules! handle_cycle_error { $error.emit(); Value::from_cycle_error($tcx) }}; - ([fatal_cycle $($rest:tt)*][$tcx:expr, $error:expr]) => {{ + ([(fatal_cycle) $($rest:tt)*][$tcx:expr, $error:expr]) => {{ $error.emit(); $tcx.sess.abort_if_errors(); unreachable!() }}; - ([cycle_delay_bug $($rest:tt)*][$tcx:expr, $error:expr]) => {{ + ([(cycle_delay_bug) $($rest:tt)*][$tcx:expr, $error:expr]) => {{ $error.delay_as_bug(); Value::from_cycle_error($tcx) }}; - ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => { - handle_cycle_error!([$($($modifiers)*)*][$($args)*]) + ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { + handle_cycle_error!([$($modifiers)*][$($args)*]) }; } @@ -271,11 +271,11 @@ macro_rules! is_anon { ([]) => {{ false }}; - ([anon $($rest:tt)*]) => {{ + ([(anon) $($rest:tt)*]) => {{ true }}; - ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*]) => { - is_anon!([$($($modifiers)*)*]) + ([$other:tt $($modifiers:tt)*]) => { + is_anon!([$($modifiers)*]) }; } @@ -283,11 +283,11 @@ macro_rules! is_eval_always { ([]) => {{ false }}; - ([eval_always $($rest:tt)*]) => {{ + ([(eval_always) $($rest:tt)*]) => {{ true }}; - ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*]) => { - is_eval_always!([$($($modifiers)*)*]) + ([$other:tt $($modifiers:tt)*]) => { + is_eval_always!([$($modifiers)*]) }; } @@ -295,11 +295,11 @@ macro_rules! hash_result { ([][$hcx:expr, $result:expr]) => {{ dep_graph::hash_result($hcx, &$result) }}; - ([no_hash $($rest:tt)*][$hcx:expr, $result:expr]) => {{ + ([(no_hash) $($rest:tt)*][$hcx:expr, $result:expr]) => {{ None }}; - ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => { - hash_result!([$($($modifiers)*)*][$($args)*]) + ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { + hash_result!([$($modifiers)*][$($args)*]) }; } From abbead78f7ab2d27ebf556970695472d1cdad44e Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sat, 2 Oct 2021 14:07:08 -0700 Subject: [PATCH 11/22] rustdoc: Improve doctest pass's name and module's name As the docs at the top of the file say, it is an overloaded pass and actually runs two lints. --- .../passes/calculate_doc_coverage.rs | 2 +- ...t_lints.rs => check_doc_test_visibility.rs} | 18 +++++++++--------- src/librustdoc/passes/mod.rs | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) rename src/librustdoc/passes/{doc_test_lints.rs => check_doc_test_visibility.rs} (90%) diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 721af3313d27f..5e3bd41b85c7e 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -2,7 +2,7 @@ use crate::clean; use crate::core::DocContext; use crate::fold::{self, DocFolder}; use crate::html::markdown::{find_testable_code, ErrorCodes}; -use crate::passes::doc_test_lints::{should_have_doc_example, Tests}; +use crate::passes::check_doc_test_visibility::{should_have_doc_example, Tests}; use crate::passes::Pass; use rustc_hir as hir; use rustc_lint::builtin::MISSING_DOCS; diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/check_doc_test_visibility.rs similarity index 90% rename from src/librustdoc/passes/doc_test_lints.rs rename to src/librustdoc/passes/check_doc_test_visibility.rs index 279d0dbda82ee..1f7d6054233dd 100644 --- a/src/librustdoc/passes/doc_test_lints.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -1,6 +1,6 @@ //! This pass is overloaded and runs two different lints. //! -//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests +//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests. //! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doctests. use super::Pass; @@ -15,23 +15,23 @@ use rustc_middle::lint::LintLevelSource; use rustc_session::lint; use rustc_span::symbol::sym; -crate const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass { - name: "check-private-items-doc-tests", - run: check_private_items_doc_tests, - description: "check private items doc tests", +crate const CHECK_DOC_TEST_VISIBILITY: Pass = Pass { + name: "check_doc_test_visibility", + run: check_doc_test_visibility, + description: "run various visibility-related lints on doctests", }; -struct PrivateItemDocTestLinter<'a, 'tcx> { +struct DocTestVisibilityLinter<'a, 'tcx> { cx: &'a mut DocContext<'tcx>, } -crate fn check_private_items_doc_tests(krate: Crate, cx: &mut DocContext<'_>) -> Crate { - let mut coll = PrivateItemDocTestLinter { cx }; +crate fn check_doc_test_visibility(krate: Crate, cx: &mut DocContext<'_>) -> Crate { + let mut coll = DocTestVisibilityLinter { cx }; coll.fold_crate(krate) } -impl<'a, 'tcx> DocFolder for PrivateItemDocTestLinter<'a, 'tcx> { +impl<'a, 'tcx> DocFolder for DocTestVisibilityLinter<'a, 'tcx> { fn fold_item(&mut self, item: Item) -> Option { let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new); diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 0e86fe45640f8..99ac87db4ff3f 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -33,8 +33,8 @@ crate use self::propagate_doc_cfg::PROPAGATE_DOC_CFG; crate mod collect_intra_doc_links; crate use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS; -mod doc_test_lints; -crate use self::doc_test_lints::CHECK_PRIVATE_ITEMS_DOC_TESTS; +mod check_doc_test_visibility; +crate use self::check_doc_test_visibility::CHECK_DOC_TEST_VISIBILITY; mod collect_trait_impls; crate use self::collect_trait_impls::COLLECT_TRAIT_IMPLS; @@ -79,7 +79,7 @@ crate enum Condition { /// The full list of passes. crate const PASSES: &[Pass] = &[ - CHECK_PRIVATE_ITEMS_DOC_TESTS, + CHECK_DOC_TEST_VISIBILITY, STRIP_HIDDEN, UNINDENT_COMMENTS, STRIP_PRIVATE, @@ -97,7 +97,7 @@ crate const PASSES: &[Pass] = &[ crate const DEFAULT_PASSES: &[ConditionalPass] = &[ ConditionalPass::always(COLLECT_TRAIT_IMPLS), ConditionalPass::always(UNINDENT_COMMENTS), - ConditionalPass::always(CHECK_PRIVATE_ITEMS_DOC_TESTS), + ConditionalPass::always(CHECK_DOC_TEST_VISIBILITY), ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden), ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate), ConditionalPass::new(STRIP_PRIV_IMPORTS, WhenDocumentPrivate), From 3da9dea49136929532a9dfb778d29991eef22af2 Mon Sep 17 00:00:00 2001 From: Hameer Abbasi Date: Sun, 3 Oct 2021 04:08:11 +0200 Subject: [PATCH 12/22] Add test for issue 89118. --- src/test/ui/traits/issue-89118.rs | 32 ++++++++++++++ src/test/ui/traits/issue-89118.stderr | 63 +++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 src/test/ui/traits/issue-89118.rs create mode 100644 src/test/ui/traits/issue-89118.stderr diff --git a/src/test/ui/traits/issue-89118.rs b/src/test/ui/traits/issue-89118.rs new file mode 100644 index 0000000000000..02b6bceae50e3 --- /dev/null +++ b/src/test/ui/traits/issue-89118.rs @@ -0,0 +1,32 @@ +trait BufferMut {} +struct Ctx(D); + +trait BufferUdpStateContext {} +impl BufferUdpStateContext for C {} + +trait StackContext +where + Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, +{ + type Dispatcher; +} + +trait TimerContext { + type Handler; +} +impl TimerContext for C +where + C: StackContext, + //~^ ERROR: is not satisfied [E0277] +{ + type Handler = Ctx; + //~^ ERROR: is not satisfied [E0277] +} + +struct EthernetWorker(C) +where + Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>; +impl EthernetWorker {} +//~^ ERROR: is not satisfied [E0277] + +fn main() {} diff --git a/src/test/ui/traits/issue-89118.stderr b/src/test/ui/traits/issue-89118.stderr new file mode 100644 index 0000000000000..7f45fb83cef08 --- /dev/null +++ b/src/test/ui/traits/issue-89118.stderr @@ -0,0 +1,63 @@ +error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied + --> $DIR/issue-89118.rs:19:8 + | +LL | C: StackContext, + | ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | +note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>` + --> $DIR/issue-89118.rs:5:23 + | +LL | impl BufferUdpStateContext for C {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required by a bound in `StackContext` + --> $DIR/issue-89118.rs:9:14 + | +LL | trait StackContext + | ------------ required by a bound in this +LL | where +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext` + +error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied + --> $DIR/issue-89118.rs:22:20 + | +LL | type Handler = Ctx; + | ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | +note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>` + --> $DIR/issue-89118.rs:5:23 + | +LL | impl BufferUdpStateContext for C {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required by a bound in `StackContext` + --> $DIR/issue-89118.rs:9:14 + | +LL | trait StackContext + | ------------ required by a bound in this +LL | where +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext` + +error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied + --> $DIR/issue-89118.rs:29:9 + | +LL | impl EthernetWorker {} + | ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | +note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>` + --> $DIR/issue-89118.rs:5:23 + | +LL | impl BufferUdpStateContext for C {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required by a bound in `EthernetWorker` + --> $DIR/issue-89118.rs:28:14 + | +LL | struct EthernetWorker(C) + | -------------- required by a bound in this +LL | where +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EthernetWorker` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. From dc4043075e3a6c879218615933e88358abc2e01b Mon Sep 17 00:00:00 2001 From: Hameer Abbasi Date: Sun, 3 Oct 2021 05:24:45 +0200 Subject: [PATCH 13/22] Move test to correct path. --- .../normalize-under-binder}/issue-89118.rs | 6 +++--- .../normalize-under-binder}/issue-89118.stderr | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename src/test/ui/{traits => higher-rank-trait-bounds/normalize-under-binder}/issue-89118.rs (80%) rename src/test/ui/{traits => higher-rank-trait-bounds/normalize-under-binder}/issue-89118.stderr (100%) diff --git a/src/test/ui/traits/issue-89118.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs similarity index 80% rename from src/test/ui/traits/issue-89118.rs rename to src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs index 02b6bceae50e3..fffb54f86ca03 100644 --- a/src/test/ui/traits/issue-89118.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs @@ -17,16 +17,16 @@ trait TimerContext { impl TimerContext for C where C: StackContext, - //~^ ERROR: is not satisfied [E0277] + //~^ ERROR: is not satisfied [E0277] { type Handler = Ctx; - //~^ ERROR: is not satisfied [E0277] + //~^ ERROR: is not satisfied [E0277] } struct EthernetWorker(C) where Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>; impl EthernetWorker {} -//~^ ERROR: is not satisfied [E0277] +//~^ ERROR: is not satisfied [E0277] fn main() {} diff --git a/src/test/ui/traits/issue-89118.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr similarity index 100% rename from src/test/ui/traits/issue-89118.stderr rename to src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr From d6a7e74c81fbe412b7041a27d7daa80e9198783a Mon Sep 17 00:00:00 2001 From: Matthias Kaak Date: Sat, 2 Oct 2021 23:14:48 +0000 Subject: [PATCH 14/22] Combined 4 commits into 1 Fixed numerus of error message Removed superfluous argument Using pluralize!() instead of code duplication Adjusted a test --- .../src/traits/error_reporting/suggestions.rs | 10 ++++++++-- src/test/ui/associated-types/impl-wf-cycle-1.stderr | 6 +++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 325126483b9ce..b001badd2be20 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -10,7 +10,9 @@ use crate::traits::normalize_projection_type; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; -use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style}; +use rustc_errors::{ + error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style, +}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; @@ -2273,7 +2275,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { parent_trait_ref = child_trait_ref; } if count > 0 { - err.note(&format!("{} redundant requirements hidden", count)); + err.note(&format!( + "{} redundant requirement{} hidden", + count, + pluralize!(count) + )); err.note(&format!( "required because of the requirements on the impl of `{}` for `{}`", parent_trait_ref.print_only_trait_path(), diff --git a/src/test/ui/associated-types/impl-wf-cycle-1.stderr b/src/test/ui/associated-types/impl-wf-cycle-1.stderr index 1d8d2b0149d21..73167d0831104 100644 --- a/src/test/ui/associated-types/impl-wf-cycle-1.stderr +++ b/src/test/ui/associated-types/impl-wf-cycle-1.stderr @@ -15,7 +15,7 @@ note: required because of the requirements on the impl of `Grault` for `(T,)` | LL | impl Grault for (T,) | ^^^^^^ ^^^^ - = note: 1 redundant requirements hidden + = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Grault` for `(T,)` error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` @@ -29,7 +29,7 @@ note: required because of the requirements on the impl of `Grault` for `(T,)` | LL | impl Grault for (T,) | ^^^^^^ ^^^^ - = note: 1 redundant requirements hidden + = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Grault` for `(T,)` error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` @@ -43,7 +43,7 @@ note: required because of the requirements on the impl of `Grault` for `(T,)` | LL | impl Grault for (T,) | ^^^^^^ ^^^^ - = note: 1 redundant requirements hidden + = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Grault` for `(T,)` error: aborting due to 3 previous errors From cf19131cb356591d27dded5bdb1d00df1bd077c9 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Sun, 3 Oct 2021 14:14:35 +0200 Subject: [PATCH 15/22] Try to recover from a `=>` -> `=` or `->` typo in a match arm --- compiler/rustc_parse/src/parser/expr.rs | 16 +++++++++++++++- src/test/ui/parser/issue-89396.fixed | 16 ++++++++++++++++ src/test/ui/parser/issue-89396.rs | 16 ++++++++++++++++ src/test/ui/parser/issue-89396.stderr | 20 ++++++++++++++++++++ 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/parser/issue-89396.fixed create mode 100644 src/test/ui/parser/issue-89396.rs create mode 100644 src/test/ui/parser/issue-89396.stderr diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index c5417ea23f219..e6a0c4c79524f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2322,7 +2322,21 @@ impl<'a> Parser<'a> { None }; let arrow_span = this.token.span; - this.expect(&token::FatArrow)?; + if let Err(mut err) = this.expect(&token::FatArrow) { + // We might have a `=>` -> `=` or `->` typo (issue #89396). + if let token::Eq | token::RArrow = this.token.kind { + err.span_suggestion( + this.token.span, + "try using a fat arrow here", + "=>".to_string(), + Applicability::MaybeIncorrect, + ); + err.emit(); + this.bump(); + } else { + return Err(err); + } + } let arm_start_span = this.token.span; let expr = this.parse_expr_res(Restrictions::STMT_EXPR, None).map_err(|mut err| { diff --git a/src/test/ui/parser/issue-89396.fixed b/src/test/ui/parser/issue-89396.fixed new file mode 100644 index 0000000000000..823ad8cd1f8df --- /dev/null +++ b/src/test/ui/parser/issue-89396.fixed @@ -0,0 +1,16 @@ +// Regression test for issue #89396: Try to recover from a +// `=>` -> `=` or `->` typo in a match arm. + +// run-rustfix + +fn main() { + let opt = Some(42); + let _ = match opt { + Some(_) => true, + //~^ ERROR: expected one of + //~| HELP: try using a fat arrow here + None => false, + //~^ ERROR: expected one of + //~| HELP: try using a fat arrow here + }; +} diff --git a/src/test/ui/parser/issue-89396.rs b/src/test/ui/parser/issue-89396.rs new file mode 100644 index 0000000000000..f1d9efa524f46 --- /dev/null +++ b/src/test/ui/parser/issue-89396.rs @@ -0,0 +1,16 @@ +// Regression test for issue #89396: Try to recover from a +// `=>` -> `=` or `->` typo in a match arm. + +// run-rustfix + +fn main() { + let opt = Some(42); + let _ = match opt { + Some(_) = true, + //~^ ERROR: expected one of + //~| HELP: try using a fat arrow here + None -> false, + //~^ ERROR: expected one of + //~| HELP: try using a fat arrow here + }; +} diff --git a/src/test/ui/parser/issue-89396.stderr b/src/test/ui/parser/issue-89396.stderr new file mode 100644 index 0000000000000..504420574e249 --- /dev/null +++ b/src/test/ui/parser/issue-89396.stderr @@ -0,0 +1,20 @@ +error: expected one of `=>`, `if`, or `|`, found `=` + --> $DIR/issue-89396.rs:9:17 + | +LL | Some(_) = true, + | ^ + | | + | expected one of `=>`, `if`, or `|` + | help: try using a fat arrow here: `=>` + +error: expected one of `=>`, `@`, `if`, or `|`, found `->` + --> $DIR/issue-89396.rs:12:14 + | +LL | None -> false, + | ^^ + | | + | expected one of `=>`, `@`, `if`, or `|` + | help: try using a fat arrow here: `=>` + +error: aborting due to 2 previous errors + From 9626f2bd84ccf99635dfdbca3da782db3596190a Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Sat, 2 Oct 2021 22:18:11 +0200 Subject: [PATCH 16/22] Fix extra `non_snake_case` warning for shorthand field bindings --- compiler/rustc_lint/src/nonstandard_style.rs | 13 +++++++------ src/test/ui/lint/issue-89469.rs | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/lint/issue-89469.rs diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 03344973bb3e6..bcddc4f3d7643 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -437,12 +437,13 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { if let hir::Node::Pat(parent_pat) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid)) { if let PatKind::Struct(_, field_pats, _) = &parent_pat.kind { - for field in field_pats.iter() { - if field.ident != ident { - // Only check if a new name has been introduced, to avoid warning - // on both the struct definition and this pattern. - self.check_snake_case(cx, "variable", &ident); - } + if field_pats + .iter() + .any(|field| !field.is_shorthand && field.pat.hir_id == p.hir_id) + { + // Only check if a new name has been introduced, to avoid warning + // on both the struct definition and this pattern. + self.check_snake_case(cx, "variable", &ident); } return; } diff --git a/src/test/ui/lint/issue-89469.rs b/src/test/ui/lint/issue-89469.rs new file mode 100644 index 0000000000000..3a6ab452840ac --- /dev/null +++ b/src/test/ui/lint/issue-89469.rs @@ -0,0 +1,20 @@ +// Regression test for #89469, where an extra non_snake_case warning was +// reported for a shorthand field binding. + +// check-pass +#![deny(non_snake_case)] + +#[allow(non_snake_case)] +struct Entry { + A: u16, + a: u16 +} + +fn foo() -> Entry {todo!()} + +pub fn f() { + let Entry { A, a } = foo(); + let _ = (A, a); +} + +fn main() {} From 6dd6e7c002bae653a3db236e2c0d5ec25f8810b5 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sun, 3 Oct 2021 17:44:07 +0200 Subject: [PATCH 17/22] Added tracking issue numbers for int_abs_diff. --- library/core/src/num/int_macros.rs | 2 +- library/core/src/num/uint_macros.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 187be5d47573a..14a3a1dda8eb5 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2244,7 +2244,7 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").abs_diff(-120), 20", stringify!($UnsignedT), ");")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.abs_diff(", stringify!($SelfT), "::MAX), ", stringify!($UnsignedT), "::MAX);")] /// ``` - #[unstable(feature = "int_abs_diff", issue = "none")] + #[unstable(feature = "int_abs_diff", issue = "89492")] #[inline] pub const fn abs_diff(self, other: Self) -> $UnsignedT { if self < other { diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index a5f12447fdc32..4fdba778b3406 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1501,7 +1501,7 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(80), 20", stringify!($SelfT), ");")] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(110), 10", stringify!($SelfT), ");")] /// ``` - #[unstable(feature = "int_abs_diff", issue = "none")] + #[unstable(feature = "int_abs_diff", issue = "89492")] #[inline] pub const fn abs_diff(self, other: Self) -> Self { if mem::size_of::() == 1 { From e34fd546111c3cad82c91a9f466284d55a53e5fb Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Sun, 3 Oct 2021 17:58:10 +0200 Subject: [PATCH 18/22] Deny `where` clauses on `auto` traits --- .../rustc_ast_passes/src/ast_validation.rs | 49 ++++++++++++++----- .../auto-traits/auto-trait-validation.fixed | 13 +++++ .../ui/auto-traits/auto-trait-validation.rs | 8 ++- .../auto-traits/auto-trait-validation.stderr | 31 +++++++----- src/test/ui/auto-traits/issue-23080-2.stderr | 6 +-- src/test/ui/auto-traits/issue-23080.stderr | 13 +++-- src/test/ui/auto-traits/issue-84075.rs | 16 ++++++ src/test/ui/auto-traits/issue-84075.stderr | 11 +++++ .../typeck-auto-trait-no-supertraits-2.rs | 1 + .../typeck-auto-trait-no-supertraits-2.stderr | 18 +++++-- .../typeck-auto-trait-no-supertraits.stderr | 8 +-- .../supertrait-auto-trait.stderr | 8 +-- 12 files changed, 135 insertions(+), 47 deletions(-) create mode 100644 src/test/ui/auto-traits/auto-trait-validation.fixed create mode 100644 src/test/ui/auto-traits/issue-84075.rs create mode 100644 src/test/ui/auto-traits/issue-84075.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 24108f779c818..0f5580db30f63 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -683,31 +683,53 @@ impl<'a> AstValidator<'a> { } } + fn emit_e0568(&self, span: Span, ident_span: Span) { + struct_span_err!( + self.session, + span, + E0568, + "auto traits cannot have super traits or lifetime bounds" + ) + .span_label(ident_span, "auto trait cannot have super traits or lifetime bounds") + .span_suggestion( + span, + "remove the super traits or lifetime bounds", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); + } + fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) { - if let [first @ last] | [first, .., last] = &bounds[..] { - let span = first.span().to(last.span()); - struct_span_err!(self.session, span, E0568, "auto traits cannot have super traits") - .span_label(ident_span, "auto trait cannot have super traits") - .span_suggestion( - span, - "remove the super traits", - String::new(), - Applicability::MachineApplicable, - ) - .emit(); + if let [.., last] = &bounds[..] { + let span = ident_span.shrink_to_hi().to(last.span()); + self.emit_e0568(span, ident_span); + } + } + + fn deny_where_clause(&self, where_clause: &WhereClause, ident_span: Span) { + if !where_clause.predicates.is_empty() { + self.emit_e0568(where_clause.span, ident_span); } } fn deny_items(&self, trait_items: &[P], ident_span: Span) { if !trait_items.is_empty() { let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect(); + let total_span = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span); struct_span_err!( self.session, spans, E0380, - "auto traits cannot have methods or associated items" + "auto traits cannot have associated items" + ) + .span_suggestion( + total_span, + "remove these associated items", + String::new(), + Applicability::MachineApplicable, ) - .span_label(ident_span, "auto trait cannot have items") + .span_label(ident_span, "auto trait cannot have associated items") .emit(); } } @@ -1184,6 +1206,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // Auto traits cannot have generics, super traits nor contain items. self.deny_generic_params(generics, item.ident.span); self.deny_super_traits(bounds, item.ident.span); + self.deny_where_clause(&generics.where_clause, item.ident.span); self.deny_items(trait_items, item.ident.span); } self.no_questions_in_bounds(bounds, "supertraits", true); diff --git a/src/test/ui/auto-traits/auto-trait-validation.fixed b/src/test/ui/auto-traits/auto-trait-validation.fixed new file mode 100644 index 0000000000000..da878ac6222bb --- /dev/null +++ b/src/test/ui/auto-traits/auto-trait-validation.fixed @@ -0,0 +1,13 @@ +#![feature(auto_traits)] + +// run-rustfix + +auto trait Generic {} +//~^ auto traits cannot have generic parameters [E0567] +auto trait Bound {} +//~^ auto traits cannot have super traits or lifetime bounds [E0568] +auto trait LifetimeBound {} +//~^ auto traits cannot have super traits or lifetime bounds [E0568] +auto trait MyTrait { } +//~^ auto traits cannot have associated items [E0380] +fn main() {} diff --git a/src/test/ui/auto-traits/auto-trait-validation.rs b/src/test/ui/auto-traits/auto-trait-validation.rs index a997b044c8ff8..d43055e270bd5 100644 --- a/src/test/ui/auto-traits/auto-trait-validation.rs +++ b/src/test/ui/auto-traits/auto-trait-validation.rs @@ -1,9 +1,13 @@ #![feature(auto_traits)] +// run-rustfix + auto trait Generic {} //~^ auto traits cannot have generic parameters [E0567] auto trait Bound : Copy {} -//~^ auto traits cannot have super traits [E0568] +//~^ auto traits cannot have super traits or lifetime bounds [E0568] +auto trait LifetimeBound : 'static {} +//~^ auto traits cannot have super traits or lifetime bounds [E0568] auto trait MyTrait { fn foo() {} } -//~^ auto traits cannot have methods or associated items [E0380] +//~^ auto traits cannot have associated items [E0380] fn main() {} diff --git a/src/test/ui/auto-traits/auto-trait-validation.stderr b/src/test/ui/auto-traits/auto-trait-validation.stderr index 4040e66c6af77..2c380e5b09a6e 100644 --- a/src/test/ui/auto-traits/auto-trait-validation.stderr +++ b/src/test/ui/auto-traits/auto-trait-validation.stderr @@ -1,28 +1,37 @@ error[E0567]: auto traits cannot have generic parameters - --> $DIR/auto-trait-validation.rs:3:19 + --> $DIR/auto-trait-validation.rs:5:19 | LL | auto trait Generic {} | -------^^^ help: remove the parameters | | | auto trait cannot have generic parameters -error[E0568]: auto traits cannot have super traits - --> $DIR/auto-trait-validation.rs:5:20 +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/auto-trait-validation.rs:7:17 | LL | auto trait Bound : Copy {} - | ----- ^^^^ help: remove the super traits + | -----^^^^^^^ help: remove the super traits or lifetime bounds | | - | auto trait cannot have super traits + | auto trait cannot have super traits or lifetime bounds -error[E0380]: auto traits cannot have methods or associated items - --> $DIR/auto-trait-validation.rs:7:25 +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/auto-trait-validation.rs:9:25 | -LL | auto trait MyTrait { fn foo() {} } - | ------- ^^^ +LL | auto trait LifetimeBound : 'static {} + | -------------^^^^^^^^^^ help: remove the super traits or lifetime bounds | | - | auto trait cannot have items + | auto trait cannot have super traits or lifetime bounds + +error[E0380]: auto traits cannot have associated items + --> $DIR/auto-trait-validation.rs:11:25 + | +LL | auto trait MyTrait { fn foo() {} } + | ------- ---^^^----- + | | | + | | help: remove these associated items + | auto trait cannot have associated items -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0380, E0567, E0568. For more information about an error, try `rustc --explain E0380`. diff --git a/src/test/ui/auto-traits/issue-23080-2.stderr b/src/test/ui/auto-traits/issue-23080-2.stderr index efeceafdd2a7d..267a712f62fa0 100644 --- a/src/test/ui/auto-traits/issue-23080-2.stderr +++ b/src/test/ui/auto-traits/issue-23080-2.stderr @@ -1,10 +1,10 @@ -error[E0380]: auto traits cannot have methods or associated items +error[E0380]: auto traits cannot have associated items --> $DIR/issue-23080-2.rs:5:10 | LL | unsafe auto trait Trait { - | ----- auto trait cannot have items + | ----- auto trait cannot have associated items LL | type Output; - | ^^^^^^ + | -----^^^^^^- help: remove these associated items error: aborting due to previous error diff --git a/src/test/ui/auto-traits/issue-23080.stderr b/src/test/ui/auto-traits/issue-23080.stderr index 73ecb1c362e17..c1b16b2f403d7 100644 --- a/src/test/ui/auto-traits/issue-23080.stderr +++ b/src/test/ui/auto-traits/issue-23080.stderr @@ -1,10 +1,13 @@ -error[E0380]: auto traits cannot have methods or associated items +error[E0380]: auto traits cannot have associated items --> $DIR/issue-23080.rs:5:8 | -LL | unsafe auto trait Trait { - | ----- auto trait cannot have items -LL | fn method(&self) { - | ^^^^^^ +LL | unsafe auto trait Trait { + | ----- auto trait cannot have associated items +LL | fn method(&self) { + | _____- ^^^^^^ +LL | | println!("Hello"); +LL | | } + | |_____- help: remove these associated items error: aborting due to previous error diff --git a/src/test/ui/auto-traits/issue-84075.rs b/src/test/ui/auto-traits/issue-84075.rs new file mode 100644 index 0000000000000..a6afe24ea4c8b --- /dev/null +++ b/src/test/ui/auto-traits/issue-84075.rs @@ -0,0 +1,16 @@ +// Regression test for issue #84075. + +#![feature(auto_traits)] + +auto trait Magic where Self: Copy {} //~ ERROR E0568 +impl Magic for T {} + +fn copy(x: T) -> (T, T) { (x, x) } + +#[derive(Debug)] +struct NoClone; + +fn main() { + let (a, b) = copy(NoClone); + println!("{:?} {:?}", a, b); +} diff --git a/src/test/ui/auto-traits/issue-84075.stderr b/src/test/ui/auto-traits/issue-84075.stderr new file mode 100644 index 0000000000000..02dca598ec250 --- /dev/null +++ b/src/test/ui/auto-traits/issue-84075.stderr @@ -0,0 +1,11 @@ +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/issue-84075.rs:5:18 + | +LL | auto trait Magic where Self: Copy {} + | ----- ^^^^^^^^^^^^^^^^ help: remove the super traits or lifetime bounds + | | + | auto trait cannot have super traits or lifetime bounds + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0568`. diff --git a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs index 6cceaf821f6bf..98359ef51b764 100644 --- a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs +++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs @@ -2,6 +2,7 @@ #![feature(negative_impls)] auto trait Magic : Sized where Option : Magic {} //~ ERROR E0568 +//~^ ERROR E0568 impl Magic for T {} fn copy(x: T) -> (T, T) { (x, x) } diff --git a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr index 63b3300f6dbf4..4827916fa5c53 100644 --- a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr +++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr @@ -1,11 +1,19 @@ -error[E0568]: auto traits cannot have super traits - --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:20 +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:17 | LL | auto trait Magic : Sized where Option : Magic {} - | ----- ^^^^^ help: remove the super traits + | -----^^^^^^^^ help: remove the super traits or lifetime bounds | | - | auto trait cannot have super traits + | auto trait cannot have super traits or lifetime bounds -error: aborting due to previous error +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:26 + | +LL | auto trait Magic : Sized where Option : Magic {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the super traits or lifetime bounds + | | + | auto trait cannot have super traits or lifetime bounds + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0568`. diff --git a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr index 796638fc54dce..d7716f4b61f04 100644 --- a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr +++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr @@ -1,10 +1,10 @@ -error[E0568]: auto traits cannot have super traits - --> $DIR/typeck-auto-trait-no-supertraits.rs:28:19 +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/typeck-auto-trait-no-supertraits.rs:28:17 | LL | auto trait Magic: Copy {} - | ----- ^^^^ help: remove the super traits + | -----^^^^^^ help: remove the super traits or lifetime bounds | | - | auto trait cannot have super traits + | auto trait cannot have super traits or lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr index 7895e50eef5c4..8405d7ddc7aa5 100644 --- a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr +++ b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr @@ -1,10 +1,10 @@ -error[E0568]: auto traits cannot have super traits - --> $DIR/supertrait-auto-trait.rs:8:19 +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/supertrait-auto-trait.rs:8:17 | LL | auto trait Magic: Copy {} - | ----- ^^^^ help: remove the super traits + | -----^^^^^^ help: remove the super traits or lifetime bounds | | - | auto trait cannot have super traits + | auto trait cannot have super traits or lifetime bounds error[E0277]: the trait bound `NoClone: Copy` is not satisfied --> $DIR/supertrait-auto-trait.rs:16:23 From 55a3c8636da6266e22d0c077cd4a58d40a0613ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 4 Oct 2021 08:37:24 +0300 Subject: [PATCH 19/22] :arrow_up: rust-analyzer --- src/tools/rust-analyzer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 009e6ceb1ddcd..4b7675fcc30d3 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 009e6ceb1ddcd27a9ced3bcb7d0ef823379185a1 +Subproject commit 4b7675fcc30d3e2c05eafc68a5724db66b58142c From 00152d89776b632905cfa4ae58e594055298c9c8 Mon Sep 17 00:00:00 2001 From: Kornel Date: Sun, 29 Aug 2021 23:21:33 +0100 Subject: [PATCH 20/22] Stabilize try_reserve --- compiler/rustc_data_structures/src/sso/map.rs | 2 +- compiler/rustc_data_structures/src/sso/set.rs | 2 +- compiler/rustc_middle/src/lib.rs | 1 - library/alloc/src/collections/mod.rs | 4 ++-- library/alloc/src/collections/vec_deque/mod.rs | 6 ++---- library/alloc/src/string.rs | 6 ++---- library/alloc/src/vec/mod.rs | 6 ++---- library/alloc/tests/lib.rs | 1 - library/std/src/collections/hash/map.rs | 3 +-- library/std/src/collections/hash/set.rs | 3 +-- library/std/src/collections/mod.rs | 2 +- library/std/src/error.rs | 2 +- library/std/src/lib.rs | 1 - src/test/ui/closures/issue-87814-2.rs | 1 - .../ui/feature-gates/feature-gate-try_reserve.rs | 4 ---- .../ui/feature-gates/feature-gate-try_reserve.stderr | 12 ------------ 16 files changed, 14 insertions(+), 42 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-try_reserve.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-try_reserve.stderr diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs index e249886e9bc01..2de05cd4e5679 100644 --- a/compiler/rustc_data_structures/src/sso/map.rs +++ b/compiler/rustc_data_structures/src/sso/map.rs @@ -31,7 +31,7 @@ const SSO_ARRAY_SIZE: usize = 8; // // Missing HashMap API: // all hasher-related -// try_reserve (unstable) +// try_reserve // shrink_to (unstable) // drain_filter (unstable) // into_keys/into_values (unstable) diff --git a/compiler/rustc_data_structures/src/sso/set.rs b/compiler/rustc_data_structures/src/sso/set.rs index 23cff0206c530..29baf4e1ddb66 100644 --- a/compiler/rustc_data_structures/src/sso/set.rs +++ b/compiler/rustc_data_structures/src/sso/set.rs @@ -13,7 +13,7 @@ use super::map::SsoHashMap; // // Missing HashSet API: // all hasher-related -// try_reserve (unstable) +// try_reserve // shrink_to (unstable) // drain_filter (unstable) // replace diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 02f0294c8ad25..344165b69ec49 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -54,7 +54,6 @@ #![feature(thread_local_const_init)] #![feature(trusted_step)] #![feature(try_blocks)] -#![feature(try_reserve)] #![feature(try_reserve_kind)] #![feature(nonzero_ops)] #![recursion_limit = "512"] diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 4e31df8b4b8c2..77d28bdfe6475 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -57,7 +57,7 @@ use core::fmt::Display; /// The error type for `try_reserve` methods. #[derive(Clone, PartialEq, Eq, Debug)] -#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] +#[stable(feature = "try_reserve", since = "1.57.0")] pub struct TryReserveError { kind: TryReserveErrorKind, } @@ -126,7 +126,7 @@ impl From for TryReserveErrorKind { } } -#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] +#[stable(feature = "try_reserve", since = "1.57.0")] impl Display for TryReserveError { fn fmt( &self, diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 4a2b0b33bf2b2..081a695f68a3f 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -711,7 +711,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::TryReserveError; /// use std::collections::VecDeque; /// @@ -730,7 +729,7 @@ impl VecDeque { /// } /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.try_reserve(additional) } @@ -749,7 +748,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::TryReserveError; /// use std::collections::VecDeque; /// @@ -768,7 +766,7 @@ impl VecDeque { /// } /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { let old_cap = self.cap(); let used_cap = self.len() + 1; diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 92a17cc75ef8b..d88b8e398985a 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1009,7 +1009,6 @@ impl String { /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::TryReserveError; /// /// fn process_data(data: &str) -> Result { @@ -1025,7 +1024,7 @@ impl String { /// } /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.vec.try_reserve(additional) } @@ -1049,7 +1048,6 @@ impl String { /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::TryReserveError; /// /// fn process_data(data: &str) -> Result { @@ -1065,7 +1063,7 @@ impl String { /// } /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.vec.try_reserve_exact(additional) } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index f3a30d0982569..8db2c16d11e46 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -849,7 +849,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::TryReserveError; /// /// fn process_data(data: &[u32]) -> Result, TryReserveError> { @@ -867,7 +866,7 @@ impl Vec { /// } /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.buf.try_reserve(self.len, additional) } @@ -892,7 +891,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::TryReserveError; /// /// fn process_data(data: &[u32]) -> Result, TryReserveError> { @@ -910,7 +908,7 @@ impl Vec { /// } /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.buf.try_reserve_exact(self.len, additional) } diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index cae4dae708e59..dfd3f4ccb3979 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -8,7 +8,6 @@ #![feature(new_uninit)] #![feature(pattern)] #![feature(trusted_len)] -#![feature(try_reserve)] #![feature(try_reserve_kind)] #![feature(unboxed_closures)] #![feature(associated_type_bounds)] diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 2de16ce3f86c7..528bb1bf6e9f9 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -625,14 +625,13 @@ where /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::HashMap; /// /// let mut map: HashMap<&str, isize> = HashMap::new(); /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?"); /// ``` #[inline] - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.base.try_reserve(additional).map_err(map_try_reserve_error) } diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 2613fbce15687..dcfe322095082 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -423,13 +423,12 @@ where /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::HashSet; /// let mut set: HashSet = HashSet::new(); /// set.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?"); /// ``` #[inline] - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.base.try_reserve(additional).map_err(map_try_reserve_error) } diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs index 6ca0525cdbe32..a19c3431989c0 100644 --- a/library/std/src/collections/mod.rs +++ b/library/std/src/collections/mod.rs @@ -420,7 +420,7 @@ pub use self::hash_map::HashMap; #[stable(feature = "rust1", since = "1.0.0")] pub use self::hash_set::HashSet; -#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] +#[stable(feature = "try_reserve", since = "1.57.0")] pub use alloc_crate::collections::TryReserveError; #[unstable( feature = "try_reserve_kind", diff --git a/library/std/src/error.rs b/library/std/src/error.rs index cc4ea27e57e8d..6ae0bc47a9462 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -595,7 +595,7 @@ impl Error for char::ParseCharError { } } -#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] +#[stable(feature = "try_reserve", since = "1.57.0")] impl Error for alloc::collections::TryReserveError {} #[unstable(feature = "duration_checked_float", issue = "83400")] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index b33a3c5d22fe1..0ba4e85886caa 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -331,7 +331,6 @@ #![feature(total_cmp)] #![feature(trace_macros)] #![feature(try_blocks)] -#![feature(try_reserve)] #![feature(try_reserve_kind)] #![feature(unboxed_closures)] #![feature(unwrap_infallible)] diff --git a/src/test/ui/closures/issue-87814-2.rs b/src/test/ui/closures/issue-87814-2.rs index 7a5facdac58c3..efe77f90f0658 100644 --- a/src/test/ui/closures/issue-87814-2.rs +++ b/src/test/ui/closures/issue-87814-2.rs @@ -1,5 +1,4 @@ // check-pass -#![feature(try_reserve)] fn main() { let mut schema_all: (Vec, Vec) = (vec![], vec![]); diff --git a/src/test/ui/feature-gates/feature-gate-try_reserve.rs b/src/test/ui/feature-gates/feature-gate-try_reserve.rs deleted file mode 100644 index a19dd58da11b3..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-try_reserve.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - let v = Vec::new(); - v.try_reserve(10); //~ ERROR: use of unstable library feature 'try_reserve' -} diff --git a/src/test/ui/feature-gates/feature-gate-try_reserve.stderr b/src/test/ui/feature-gates/feature-gate-try_reserve.stderr deleted file mode 100644 index 4da9a23a1bd5f..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-try_reserve.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: use of unstable library feature 'try_reserve': new API - --> $DIR/feature-gate-try_reserve.rs:3:7 - | -LL | v.try_reserve(10); - | ^^^^^^^^^^^ - | - = note: see issue #48043 for more information - = help: add `#![feature(try_reserve)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. From 079c075f24d2aae84cd6715f350cf56420816f63 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Mon, 4 Oct 2021 22:13:00 +0200 Subject: [PATCH 21/22] Use `TokenKind::similar_tokens()` --- compiler/rustc_ast/src/token.rs | 1 + compiler/rustc_parse/src/parser/expr.rs | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 3a65ffe41ae87..db066d7c6a519 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -295,6 +295,7 @@ impl TokenKind { match *self { Comma => Some(vec![Dot, Lt, Semi]), Semi => Some(vec![Colon, Comma]), + FatArrow => Some(vec![Eq, RArrow]), _ => None, } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e6a0c4c79524f..79f46be73f6c2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2324,7 +2324,10 @@ impl<'a> Parser<'a> { let arrow_span = this.token.span; if let Err(mut err) = this.expect(&token::FatArrow) { // We might have a `=>` -> `=` or `->` typo (issue #89396). - if let token::Eq | token::RArrow = this.token.kind { + if TokenKind::FatArrow + .similar_tokens() + .map_or(false, |similar_tokens| similar_tokens.contains(&this.token.kind)) + { err.span_suggestion( this.token.span, "try using a fat arrow here", From e5d01785f877161b2a2f2eafb6818f3463b5287e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 4 Oct 2021 18:13:00 -0400 Subject: [PATCH 22/22] update Miri --- Cargo.lock | 32 ++++++++++++++------------------ src/tools/miri | 2 +- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4e1ab6c1e4a8..adf14bfddfd7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -360,7 +360,7 @@ version = "0.1.0" dependencies = [ "directories", "rustc-workspace-hack", - "rustc_version", + "rustc_version 0.3.3", "serde", "serde_json", "vergen", @@ -1092,19 +1092,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "env_logger" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54532e3223c5af90a6a757c90b5c5521564b07e5e7a958681bcd2afad421cdcd" -dependencies = [ - "atty", - "humantime 2.0.1", - "log", - "regex", - "termcolor", -] - [[package]] name = "env_logger" version = "0.9.0" @@ -2250,7 +2237,7 @@ version = "0.1.0" dependencies = [ "colored", "compiletest_rs", - "env_logger 0.8.1", + "env_logger 0.9.0", "getrandom 0.2.0", "hex 0.4.2", "libc", @@ -2258,7 +2245,7 @@ dependencies = [ "measureme", "rand 0.8.4", "rustc-workspace-hack", - "rustc_version", + "rustc_version 0.4.0", "shell-escape", "smallvec", ] @@ -4548,6 +4535,15 @@ dependencies = [ "semver 0.11.0", ] +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.3", +] + [[package]] name = "rustdoc" version = "0.0.0" @@ -4908,9 +4904,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "smallvec" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" [[package]] name = "snap" diff --git a/src/tools/miri b/src/tools/miri index 035933186957c..18667a8565967 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 035933186957cf81c488261fb48a98bf523e8006 +Subproject commit 18667a856596713fc4479f99b96afc7f03aa995c