From 16e10bf81ee73f61cf813acef3d5dbbce4f66da2 Mon Sep 17 00:00:00 2001 From: Francesca Lovebloom Date: Wed, 7 Oct 2020 15:46:05 -0700 Subject: [PATCH 01/23] Revert "Allow dynamic linking for iOS/tvOS targets." This reverts commit 56e115a2627ba8bdd2e66c759457af96b2b0286a. --- compiler/rustc_target/src/spec/apple_sdk_base.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs index e34277d5af04c..1b17c2c278f9a 100644 --- a/compiler/rustc_target/src/spec/apple_sdk_base.rs +++ b/compiler/rustc_target/src/spec/apple_sdk_base.rs @@ -34,6 +34,7 @@ fn link_env_remove(arch: Arch) -> Vec { pub fn opts(arch: Arch) -> TargetOptions { TargetOptions { cpu: target_cpu(arch), + dynamic_linking: false, executables: true, link_env_remove: link_env_remove(arch), has_elf_tls: false, From b62b352f4779072c07c110a63fd83afa9508b9e9 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 19 Oct 2020 10:02:51 -0700 Subject: [PATCH 02/23] Check for exhaustion in RangeInclusive::contains When a range has finished iteration, `is_empty` returns true, so it should also be the case that `contains` returns false. --- library/core/src/ops/range.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 4423cfc27dd17..1da186d9fbb24 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -479,13 +479,23 @@ impl> RangeInclusive { /// assert!(!(0.0..=f32::NAN).contains(&0.0)); /// assert!(!(f32::NAN..=1.0).contains(&1.0)); /// ``` + /// + /// This method always returns `false` after iteration has finished: + /// + /// ``` + /// let mut r = 3..=5; + /// assert!(r.contains(&3) && r.contains(&5)); + /// for _ in r.by_ref() {} + /// // Precise field values are unspecified here + /// assert!(!r.contains(&3) && !r.contains(&5)); + /// ``` #[stable(feature = "range_contains", since = "1.35.0")] pub fn contains(&self, item: &U) -> bool where Idx: PartialOrd, U: ?Sized + PartialOrd, { - >::contains(self, item) + !self.exhausted && >::contains(self, item) } /// Returns `true` if the range contains no items. From 9fd79a39044be777a39604856d0a276484d6480f Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 19 Oct 2020 13:46:30 -0700 Subject: [PATCH 03/23] make exhausted RangeInclusive::end_bound return Excluded(end) --- library/core/src/ops/range.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 1da186d9fbb24..084ddffab0b7a 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -495,7 +495,7 @@ impl> RangeInclusive { Idx: PartialOrd, U: ?Sized + PartialOrd, { - !self.exhausted && >::contains(self, item) + >::contains(self, item) } /// Returns `true` if the range contains no items. @@ -891,7 +891,13 @@ impl RangeBounds for RangeInclusive { Included(&self.start) } fn end_bound(&self) -> Bound<&T> { - Included(&self.end) + if self.exhausted { + // When the iterator is exhausted, we usually have start == end, + // but we want the range to appear empty, containing nothing. + Excluded(&self.end) + } else { + Included(&self.end) + } } } From a9470d0522368f67d8aaa551318e3feb2d18e790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 21 Oct 2020 00:00:00 +0000 Subject: [PATCH 04/23] Simplify assert terminator only if condition evaluates to expected value --- compiler/rustc_mir/src/transform/simplify_branches.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir/src/transform/simplify_branches.rs b/compiler/rustc_mir/src/transform/simplify_branches.rs index 5f63c03993d3a..a9a45e61a38cb 100644 --- a/compiler/rustc_mir/src/transform/simplify_branches.rs +++ b/compiler/rustc_mir/src/transform/simplify_branches.rs @@ -49,9 +49,10 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches { } TerminatorKind::Assert { target, cond: Operand::Constant(ref c), expected, .. - } if (c.literal.try_eval_bool(tcx, param_env) == Some(true)) == expected => { - TerminatorKind::Goto { target } - } + } => match c.literal.try_eval_bool(tcx, param_env) { + Some(v) if v == expected => TerminatorKind::Goto { target }, + _ => continue, + }, TerminatorKind::FalseEdge { real_target, .. } => { TerminatorKind::Goto { target: real_target } } From 9202fbdbdbd60adb62839c3230738274e30f15fc Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 20 Oct 2020 17:18:08 -0700 Subject: [PATCH 05/23] Check for exhaustion in SliceIndex for RangeInclusive --- library/alloc/tests/str.rs | 29 +++++++++++++++++++++++++++++ library/core/src/ops/range.rs | 14 ++++++++++++++ library/core/src/slice/index.rs | 16 ++++++---------- library/core/src/str/traits.rs | 16 ++++++---------- library/core/tests/slice.rs | 30 ++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 20 deletions(-) diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs index ed8ee2d8823c0..834dd4656ff76 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -529,6 +529,13 @@ mod slice_index { message: "out of bounds"; } + in mod rangeinclusive_len { + data: "abcdef"; + good: data[0..=5] == "abcdef"; + bad: data[0..=6]; + message: "out of bounds"; + } + in mod range_len_len { data: "abcdef"; good: data[6..6] == ""; @@ -544,6 +551,28 @@ mod slice_index { } } + panic_cases! { + in mod rangeinclusive_exhausted { + data: "abcdef"; + + good: data[0..=5] == "abcdef"; + good: data[{ + let mut iter = 0..=5; + iter.by_ref().count(); // exhaust it + iter + }] == ""; + + // 0..=6 is out of bounds before exhaustion, so it + // stands to reason that it still would be after. + bad: data[{ + let mut iter = 0..=6; + iter.by_ref().count(); // exhaust it + iter + }]; + message: "out of bounds"; + } + } + panic_cases! { in mod range_neg_width { data: "abcdef"; diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 084ddffab0b7a..1d67e65e51f5f 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -446,6 +446,20 @@ impl RangeInclusive { } } +impl RangeInclusive { + /// Converts to an exclusive `Range` for `SliceIndex` implementations. + /// The caller is responsible for dealing with `end == usize::MAX`. + #[inline] + pub(crate) fn into_slice_range(self) -> Range { + // If we're not exhausted, we want to simply slice `start..end + 1`. + // If we are exhausted, then slicing with `end + 1..end + 1` gives us an + // empty range that is still subject to bounds-checks for that endpoint. + let exclusive_end = self.end + 1; + let start = if self.exhausted { exclusive_end } else { self.start }; + start..exclusive_end + } +} + #[stable(feature = "inclusive_range", since = "1.26.0")] impl fmt::Debug for RangeInclusive { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index f1f21c1d24b0b..660c8a2da5da0 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -376,28 +376,24 @@ unsafe impl SliceIndex<[T]> for ops::RangeInclusive { #[inline] fn get(self, slice: &[T]) -> Option<&[T]> { - if *self.end() == usize::MAX { None } else { (*self.start()..self.end() + 1).get(slice) } + if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) } } #[inline] fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { - if *self.end() == usize::MAX { - None - } else { - (*self.start()..self.end() + 1).get_mut(slice) - } + if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } } #[inline] unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. - unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) } + unsafe { self.into_slice_range().get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. - unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) } + unsafe { self.into_slice_range().get_unchecked_mut(slice) } } #[inline] @@ -405,7 +401,7 @@ unsafe impl SliceIndex<[T]> for ops::RangeInclusive { if *self.end() == usize::MAX { slice_end_index_overflow_fail(); } - (*self.start()..self.end() + 1).index(slice) + self.into_slice_range().index(slice) } #[inline] @@ -413,7 +409,7 @@ unsafe impl SliceIndex<[T]> for ops::RangeInclusive { if *self.end() == usize::MAX { slice_end_index_overflow_fail(); } - (*self.start()..self.end() + 1).index_mut(slice) + self.into_slice_range().index_mut(slice) } } diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 4f8aa246e5232..f363541431100 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -398,39 +398,35 @@ unsafe impl SliceIndex for ops::RangeInclusive { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { - if *self.end() == usize::MAX { None } else { (*self.start()..self.end() + 1).get(slice) } + if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) } } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { - if *self.end() == usize::MAX { - None - } else { - (*self.start()..self.end() + 1).get_mut(slice) - } + if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } } #[inline] unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked`. - unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) } + unsafe { self.into_slice_range().get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`. - unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) } + unsafe { self.into_slice_range().get_unchecked_mut(slice) } } #[inline] fn index(self, slice: &str) -> &Self::Output { if *self.end() == usize::MAX { str_index_overflow_fail(); } - (*self.start()..self.end() + 1).index(slice) + self.into_slice_range().index(slice) } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { if *self.end() == usize::MAX { str_index_overflow_fail(); } - (*self.start()..self.end() + 1).index_mut(slice) + self.into_slice_range().index_mut(slice) } } diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index ac5c9353ccb46..9ccc5a08dcbea 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -1341,6 +1341,14 @@ mod slice_index { message: "out of range"; } + in mod rangeinclusive_len { + data: [0, 1, 2, 3, 4, 5]; + + good: data[0..=5] == [0, 1, 2, 3, 4, 5]; + bad: data[0..=6]; + message: "out of range"; + } + in mod range_len_len { data: [0, 1, 2, 3, 4, 5]; @@ -1358,6 +1366,28 @@ mod slice_index { } } + panic_cases! { + in mod rangeinclusive_exhausted { + data: [0, 1, 2, 3, 4, 5]; + + good: data[0..=5] == [0, 1, 2, 3, 4, 5]; + good: data[{ + let mut iter = 0..=5; + iter.by_ref().count(); // exhaust it + iter + }] == []; + + // 0..=6 is out of range before exhaustion, so it + // stands to reason that it still would be after. + bad: data[{ + let mut iter = 0..=6; + iter.by_ref().count(); // exhaust it + iter + }]; + message: "out of range"; + } + } + panic_cases! { in mod range_neg_width { data: [0, 1, 2, 3, 4, 5]; From 40ab18d97dab9df68418d19ef8a40c3218142d5f Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 22 Oct 2020 23:07:48 +0200 Subject: [PATCH 06/23] improve const infer error --- compiler/rustc_middle/src/infer/unify_key.rs | 16 +++++----------- .../ui/const-generics/infer/issue-77092.stderr | 2 +- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 4d884dde39387..cf5e99845d189 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -176,17 +176,17 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> { type Error = (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>); fn unify_values(value1: &Self, value2: &Self) -> Result { - let (val, span) = match (value1.val, value2.val) { + let (val, origin) = match (value1.val, value2.val) { (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => { bug!("equating two const variables, both of which have known values") } // If one side is known, prefer that one. (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => { - (value1.val, value1.origin.span) + (value1.val, value1.origin) } (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => { - (value2.val, value2.origin.span) + (value2.val, value2.origin) } // If both sides are *unknown*, it hardly matters, does it? @@ -200,17 +200,11 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> { // universe is the minimum of the two universes, because that is // the one which contains the fewest names in scope. let universe = cmp::min(universe1, universe2); - (ConstVariableValue::Unknown { universe }, value1.origin.span) + (ConstVariableValue::Unknown { universe }, value1.origin) } }; - Ok(ConstVarValue { - origin: ConstVariableOrigin { - kind: ConstVariableOriginKind::ConstInference, - span: span, - }, - val, - }) + Ok(ConstVarValue { origin, val }) } } diff --git a/src/test/ui/const-generics/infer/issue-77092.stderr b/src/test/ui/const-generics/infer/issue-77092.stderr index e84ff8baeea53..63facbf3b8c0f 100644 --- a/src/test/ui/const-generics/infer/issue-77092.stderr +++ b/src/test/ui/const-generics/infer/issue-77092.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/issue-77092.rs:13:26 | LL | println!("{:?}", take_array_from_mut(&mut arr, i)); - | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `{_: usize}` + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `take_array_from_mut` error: aborting due to previous error From 9775ac60dcc92dbb04861863a69eacfafeea5c4c Mon Sep 17 00:00:00 2001 From: Camelid Date: Thu, 22 Oct 2020 14:22:09 -0700 Subject: [PATCH 07/23] Document inline-const in the Unstable Book --- .../src/language-features/inline-const.md | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/inline-const.md diff --git a/src/doc/unstable-book/src/language-features/inline-const.md b/src/doc/unstable-book/src/language-features/inline-const.md new file mode 100644 index 0000000000000..00e1c79ca3ff3 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/inline-const.md @@ -0,0 +1,45 @@ +# `inline_const` + +The tracking issue for this feature is: [#76001] + +------ + +This feature allows you to use inline constant expressions. For example, you can +turn this code: + +```rust +# fn add_one(x: i32) -> i32 { x + 1 } +const MY_COMPUTATION: i32 = 1 + 2 * 3 / 4; + +fn main() { + let x = add_one(MY_COMPUTATION); +} +``` + +into this code: + +```rust +#![feature(inline_const)] + +# fn add_one(x: i32) -> i32 { x + 1 } +fn main() { + let x = add_one(const { 1 + 2 * 3 / 4 }); +} +``` + +You can also use inline constant expressions in patterns: + +```rust +#![feature(inline_const)] + +const fn one() -> i32 { 1 } + +let some_int = 3; +match some_int { + const { 1 + 2 } => println!("Matched 1 + 2"), + const { one() } => println!("Matched const fn returning 1"), + _ => println!("Didn't match anything :("), +} +``` + +[#76001]: https://github.com/rust-lang/rust/issues/76001 From 09135e4e758c6fb5a3ca91924a78521f749acda9 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 23 Oct 2020 16:09:17 +0900 Subject: [PATCH 08/23] Add regression test for issue-77475 --- src/test/ui/macros/issue-77475.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/test/ui/macros/issue-77475.rs diff --git a/src/test/ui/macros/issue-77475.rs b/src/test/ui/macros/issue-77475.rs new file mode 100644 index 0000000000000..7b32a33ea4f17 --- /dev/null +++ b/src/test/ui/macros/issue-77475.rs @@ -0,0 +1,10 @@ +// check-pass +// Regression test of #77475, this used to be ICE. + +#![feature(decl_macro)] + +use crate as _; + +pub macro ice(){} + +fn main() {} From e1c524cd457bd02435a47214052320f8d4bfa999 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Fri, 23 Oct 2020 09:33:47 +0200 Subject: [PATCH 09/23] review --- compiler/rustc_middle/src/infer/unify_key.rs | 21 +++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index cf5e99845d189..16e9aafb25a54 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -175,19 +175,15 @@ impl<'tcx> UnifyKey for ty::ConstVid<'tcx> { impl<'tcx> UnifyValue for ConstVarValue<'tcx> { type Error = (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>); - fn unify_values(value1: &Self, value2: &Self) -> Result { - let (val, origin) = match (value1.val, value2.val) { + fn unify_values(&value1: &Self, &value2: &Self) -> Result { + Ok(match (value1.val, value2.val) { (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => { bug!("equating two const variables, both of which have known values") } // If one side is known, prefer that one. - (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => { - (value1.val, value1.origin) - } - (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => { - (value2.val, value2.origin) - } + (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => value1, + (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => value2, // If both sides are *unknown*, it hardly matters, does it? ( @@ -200,11 +196,12 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> { // universe is the minimum of the two universes, because that is // the one which contains the fewest names in scope. let universe = cmp::min(universe1, universe2); - (ConstVariableValue::Unknown { universe }, value1.origin) + ConstVarValue { + val: ConstVariableValue::Unknown { universe }, + origin: value1.origin, + } } - }; - - Ok(ConstVarValue { origin, val }) + }) } } From 50e34d6d658c4906a3292385b1962a3c26ce24c4 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 23 Oct 2020 18:00:18 +0900 Subject: [PATCH 10/23] Do not try to report on closures to avoid ICE --- .../nice_region_error/static_impl_trait.rs | 8 ++++++++ src/test/ui/regions/issue-78262.rs | 9 +++++++++ src/test/ui/regions/issue-78262.stderr | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 src/test/ui/regions/issue-78262.rs create mode 100644 src/test/ui/regions/issue-78262.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 441cfeea20a48..e9d5ebad7de03 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -39,6 +39,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ) if **sub_r == RegionKind::ReStatic => { // This is for an implicit `'static` requirement coming from `impl dyn Trait {}`. if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code { + // This may have a closure and it would cause ICE + // through `find_param_with_region` (#78262). + let anon_reg_sup = tcx.is_suitable_region(sup_r)?; + let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); + if fn_returns.is_empty() { + return None; + } + let param = self.find_param_with_region(sup_r, sub_r)?; let lifetime = if sup_r.has_name() { format!("lifetime `{}`", sup_r) diff --git a/src/test/ui/regions/issue-78262.rs b/src/test/ui/regions/issue-78262.rs new file mode 100644 index 0000000000000..2324152d2c081 --- /dev/null +++ b/src/test/ui/regions/issue-78262.rs @@ -0,0 +1,9 @@ +trait TT {} + +impl dyn TT { + fn func(&self) {} +} + +fn main() { + let f = |x: &dyn TT| x.func(); //~ ERROR: mismatched types +} diff --git a/src/test/ui/regions/issue-78262.stderr b/src/test/ui/regions/issue-78262.stderr new file mode 100644 index 0000000000000..580cea00ecd4f --- /dev/null +++ b/src/test/ui/regions/issue-78262.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-78262.rs:8:28 + | +LL | let f = |x: &dyn TT| x.func(); + | ^^^^ lifetime mismatch + | + = note: expected reference `&(dyn TT + 'static)` + found reference `&dyn TT` +note: the anonymous lifetime #1 defined on the body at 8:13... + --> $DIR/issue-78262.rs:8:13 + | +LL | let f = |x: &dyn TT| x.func(); + | ^^^^^^^^^^^^^^^^^^^^^ + = note: ...does not necessarily outlive the static lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 9b90e1762e6cb21baa504a27530b9aa404fbe3ac Mon Sep 17 00:00:00 2001 From: Canop Date: Thu, 1 Oct 2020 11:13:38 +0200 Subject: [PATCH 11/23] add `insert` and `insert_with` to `Option` This removes a cause of `unwrap` and code complexity. This allows replacing ``` option_value = Some(build()); option_value.as_mut().unwrap() ``` with ``` option_value.insert(build()) ``` or ``` option_value.insert_with(build) ``` It's also useful in contexts not requiring the mutability of the reference. Here's a typical cache example: ``` let checked_cache = cache.as_ref().filter(|e| e.is_valid()); let content = match checked_cache { Some(e) => &e.content, None => { cache = Some(compute_cache_entry()); // unwrap is OK because we just filled the option &cache.as_ref().unwrap().content } }; ``` It can be changed into ``` let checked_cache = cache.as_ref().filter(|e| e.is_valid()); let content = match checked_cache { Some(e) => &e.content, None => &cache.insert_with(compute_cache_entry).content, }; ``` --- library/core/src/option.rs | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 825144e5a6fbe..394be746ec2fa 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -562,6 +562,52 @@ impl Option { } } + ///////////////////////////////////////////////////////////////////////// + // Setting a new value + ///////////////////////////////////////////////////////////////////////// + + /// Inserts `v` into the option then returns a mutable reference + /// to the contained value. + /// + /// # Example + /// + /// ``` + /// #![feature(option_insert)] + /// + /// let mut o = None; + /// let v = o.insert(3); + /// assert_eq!(*v, 3); + /// ``` + #[inline] + #[unstable(feature = "option_insert", reason = "new API", issue = "none")] + pub fn insert(&mut self, v: T) -> &mut T { + self.insert_with(|| v) + } + + /// Inserts a value computed from `f` into the option, then returns a + /// mutable reference to the contained value. + /// + /// # Example + /// + /// ``` + /// #![feature(option_insert)] + /// + /// let mut o = None; + /// let v = o.insert_with(|| 3); + /// assert_eq!(*v, 3); + /// ``` + #[inline] + #[unstable(feature = "option_insert", reason = "new API", issue = "none")] + pub fn insert_with T>(&mut self, f: F) -> &mut T { + *self = Some(f()); + + match *self { + Some(ref mut v) => v, + // SAFETY: the code above just filled the option + None => unsafe { hint::unreachable_unchecked() }, + } + } + ///////////////////////////////////////////////////////////////////////// // Iterator constructors ///////////////////////////////////////////////////////////////////////// From e8df2a426959fa3ff4f65eae85e618394bf27e28 Mon Sep 17 00:00:00 2001 From: Canop Date: Thu, 1 Oct 2020 13:24:33 +0200 Subject: [PATCH 12/23] remove `option.insert_with` `option.insert` covers both needs anyway, `insert_with` is redundant. --- library/core/src/option.rs | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 394be746ec2fa..64541da300e86 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -581,25 +581,7 @@ impl Option { #[inline] #[unstable(feature = "option_insert", reason = "new API", issue = "none")] pub fn insert(&mut self, v: T) -> &mut T { - self.insert_with(|| v) - } - - /// Inserts a value computed from `f` into the option, then returns a - /// mutable reference to the contained value. - /// - /// # Example - /// - /// ``` - /// #![feature(option_insert)] - /// - /// let mut o = None; - /// let v = o.insert_with(|| 3); - /// assert_eq!(*v, 3); - /// ``` - #[inline] - #[unstable(feature = "option_insert", reason = "new API", issue = "none")] - pub fn insert_with T>(&mut self, f: F) -> &mut T { - *self = Some(f()); + *self = Some(v); match *self { Some(ref mut v) => v, From 60a96cae336b621be3a5e01cf6c87649b327f836 Mon Sep 17 00:00:00 2001 From: Canop Date: Thu, 1 Oct 2020 16:05:01 +0200 Subject: [PATCH 13/23] more tests in option.insert, code cleaning in option Code cleaning made according to suggestions in discussion on PR ##77392 impacts insert, get_or_insert and get_or_insert_with. --- library/core/src/option.rs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 64541da300e86..65575f4c41bad 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -574,17 +574,22 @@ impl Option { /// ``` /// #![feature(option_insert)] /// - /// let mut o = None; - /// let v = o.insert(3); - /// assert_eq!(*v, 3); + /// let mut opt = None; + /// let val = opt.insert(1); + /// assert_eq!(*val, 1); + /// assert_eq!(opt.unwrap(), 1); + /// let val = opt.insert(2); + /// assert_eq!(*val, 2); + /// *val = 3; + /// assert_eq!(opt.unwrap(), 3); /// ``` #[inline] - #[unstable(feature = "option_insert", reason = "new API", issue = "none")] - pub fn insert(&mut self, v: T) -> &mut T { - *self = Some(v); + #[unstable(feature = "option_insert", reason = "newly added", issue = "none")] + pub fn insert(&mut self, val: T) -> &mut T { + *self = Some(val); - match *self { - Some(ref mut v) => v, + match self { + Some(v) => v, // SAFETY: the code above just filled the option None => unsafe { hint::unreachable_unchecked() }, } @@ -839,8 +844,8 @@ impl Option { /// ``` #[inline] #[stable(feature = "option_entry", since = "1.20.0")] - pub fn get_or_insert(&mut self, v: T) -> &mut T { - self.get_or_insert_with(|| v) + pub fn get_or_insert(&mut self, val: T) -> &mut T { + self.get_or_insert_with(|| val) } /// Inserts a value computed from `f` into the option if it is [`None`], then @@ -867,8 +872,8 @@ impl Option { *self = Some(f()); } - match *self { - Some(ref mut v) => v, + match self { + Some(v) => v, // SAFETY: a `None` variant for `self` would have been replaced by a `Some` // variant in the code above. None => unsafe { hint::unreachable_unchecked() }, From cc8b77a7cf0e1179b148a70c8f760a7ba3c1debd Mon Sep 17 00:00:00 2001 From: Canop Date: Sat, 3 Oct 2020 10:29:11 +0200 Subject: [PATCH 14/23] fix naming unconsistency between function doc and prototype --- library/core/src/option.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 65575f4c41bad..8fd3bfe77b800 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -566,8 +566,7 @@ impl Option { // Setting a new value ///////////////////////////////////////////////////////////////////////// - /// Inserts `v` into the option then returns a mutable reference - /// to the contained value. + /// Inserts `value` into the option then returns a mutable reference to it. /// /// # Example /// @@ -585,8 +584,8 @@ impl Option { /// ``` #[inline] #[unstable(feature = "option_insert", reason = "newly added", issue = "none")] - pub fn insert(&mut self, val: T) -> &mut T { - *self = Some(val); + pub fn insert(&mut self, value: T) -> &mut T { + *self = Some(value); match self { Some(v) => v, @@ -825,7 +824,7 @@ impl Option { // Entry-like operations to insert if None and return a reference ///////////////////////////////////////////////////////////////////////// - /// Inserts `v` into the option if it is [`None`], then + /// Inserts `value` into the option if it is [`None`], then /// returns a mutable reference to the contained value. /// /// # Examples @@ -844,12 +843,12 @@ impl Option { /// ``` #[inline] #[stable(feature = "option_entry", since = "1.20.0")] - pub fn get_or_insert(&mut self, val: T) -> &mut T { - self.get_or_insert_with(|| val) + pub fn get_or_insert(&mut self, value: T) -> &mut T { + self.get_or_insert_with(|| value) } - /// Inserts a value computed from `f` into the option if it is [`None`], then - /// returns a mutable reference to the contained value. + /// Inserts a value computed from `f` into the option if it is [`None`], + /// then returns a mutable reference to the contained value. /// /// # Examples /// From 39557799c763d75b58cbd7235af49a29c4d1212c Mon Sep 17 00:00:00 2001 From: Canop Date: Fri, 23 Oct 2020 11:08:09 +0200 Subject: [PATCH 15/23] Update library/core/src/option.rs Co-authored-by: Mara Bos --- library/core/src/option.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 8fd3bfe77b800..4e8a74d9162a5 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -568,6 +568,8 @@ impl Option { /// Inserts `value` into the option then returns a mutable reference to it. /// + /// If the option already contains a value, the old value is dropped. + /// /// # Example /// /// ``` From 415a8e526d0e99f0e85e3b06bad9d2f2867910c5 Mon Sep 17 00:00:00 2001 From: Canop Date: Fri, 23 Oct 2020 11:09:15 +0200 Subject: [PATCH 16/23] Update library/core/src/option.rs Co-authored-by: Ivan Tham --- library/core/src/option.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 4e8a74d9162a5..a3d20f016fd98 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -562,10 +562,6 @@ impl Option { } } - ///////////////////////////////////////////////////////////////////////// - // Setting a new value - ///////////////////////////////////////////////////////////////////////// - /// Inserts `value` into the option then returns a mutable reference to it. /// /// If the option already contains a value, the old value is dropped. From 216d0fe36466ce9307a643a67afa41ebfb8c43dd Mon Sep 17 00:00:00 2001 From: Canop Date: Fri, 23 Oct 2020 11:44:58 +0200 Subject: [PATCH 17/23] add tracking issue number to option_insert feature gate --- library/core/src/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index a3d20f016fd98..3daf26208b937 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -581,7 +581,7 @@ impl Option { /// assert_eq!(opt.unwrap(), 3); /// ``` #[inline] - #[unstable(feature = "option_insert", reason = "newly added", issue = "none")] + #[unstable(feature = "option_insert", reason = "newly added", issue = "78271")] pub fn insert(&mut self, value: T) -> &mut T { *self = Some(value); From efedcb23447a805fad841c4e38d5dea0d53ec3c7 Mon Sep 17 00:00:00 2001 From: Eduardo Pinho Date: Fri, 23 Oct 2020 12:13:07 +0100 Subject: [PATCH 18/23] Update description of Empty Enum for accuracy An empty enum is similar to the never type `!`, rather than the unit type `()`. --- library/std/src/keyword_docs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index a4bbb18da5983..9b704ee9ecab2 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -346,7 +346,7 @@ mod else_keyword {} /// When data follows along with a variant, such as with rust's built-in [`Option`] type, the data /// is added as the type describes, for example `Option::Some(123)`. The same follows with /// struct-like variants, with things looking like `ComplexEnum::LotsOfThings { usual_struct_stuff: -/// true, blah: "hello!".to_string(), }`. Empty Enums are similar to () in that they cannot be +/// true, blah: "hello!".to_string(), }`. Empty Enums are similar to [`!`] in that they cannot be /// instantiated at all, and are used mainly to mess with the type system in interesting ways. /// /// For more information, take a look at the [Rust Book] or the [Reference] @@ -354,6 +354,7 @@ mod else_keyword {} /// [ADT]: https://en.wikipedia.org/wiki/Algebraic_data_type /// [Rust Book]: ../book/ch06-01-defining-an-enum.html /// [Reference]: ../reference/items/enumerations.html +/// [`!`]: primitive.never.html mod enum_keyword {} #[doc(keyword = "extern")] From 972d9e886ca8787b2b4223bd39a76ff0250dfcaf Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Fri, 23 Oct 2020 13:58:32 +0200 Subject: [PATCH 19/23] move `visit_predicate` into `TypeVisitor` --- compiler/rustc_middle/src/ty/fold.rs | 11 +++++------ compiler/rustc_middle/src/ty/structural_impls.rs | 10 ---------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 5524d91a6d533..0e5e22dcaae9f 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -30,8 +30,6 @@ //! //! These methods return true to indicate that the visitor has found what it is //! looking for, and does not need to visit anything else. - -use crate::ty::structural_impls::PredicateVisitor; use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -211,6 +209,10 @@ pub trait TypeVisitor<'tcx>: Sized { fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool { c.super_visit_with(self) } + + fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> bool { + p.super_visit_with(self) + } } /////////////////////////////////////////////////////////////////////////// @@ -868,9 +870,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { _ => ct.super_visit_with(self), } } -} -impl<'tcx> PredicateVisitor<'tcx> for HasEscapingVarsVisitor { fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool { predicate.inner.outer_exclusive_binder > self.outer_index } @@ -903,9 +903,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags); flags.intersects(self.flags) } -} -impl<'tcx> PredicateVisitor<'tcx> for HasTypeFlagsVisitor { fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool { debug!( "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}", @@ -914,6 +912,7 @@ impl<'tcx> PredicateVisitor<'tcx> for HasTypeFlagsVisitor { predicate.inner.flags.intersects(self.flags) } } + /// Collects all the late-bound regions at the innermost binding level /// into a hash set. struct LateBoundRegionsCollector { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index d9ec6bb20fda8..53521d0e9f332 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -1040,16 +1040,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { } } -pub(super) trait PredicateVisitor<'tcx>: TypeVisitor<'tcx> { - fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool; -} - -impl> PredicateVisitor<'tcx> for T { - default fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool { - predicate.super_visit_with(self) - } -} - impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn super_fold_with>(&self, folder: &mut F) -> Self { fold_list(*self, folder, |tcx, v| tcx.intern_predicates(v)) From a0ce1e095e0d89d35ff3de20541dd4faf79607da Mon Sep 17 00:00:00 2001 From: nasso Date: Fri, 23 Oct 2020 18:58:42 +0200 Subject: [PATCH 20/23] Always store Rustdoc theme when it's changed --- src/librustdoc/html/static/storage.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index a027d6845ea21..ef734f260afd5 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -94,6 +94,12 @@ function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) { var fullNewTheme = newTheme + resourcesSuffix + ".css"; var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme); + // If this new value comes from a system setting or from the previously + // saved theme, no need to save it. + if (saveTheme === true) { + updateLocalStorage("rustdoc-theme", newTheme); + } + if (styleElem.href === newHref) { return; } @@ -112,11 +118,6 @@ function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) { }); if (found === true) { styleElem.href = newHref; - // If this new value comes from a system setting or from the previously - // saved theme, no need to save it. - if (saveTheme === true) { - updateLocalStorage("rustdoc-theme", newTheme); - } } } From c3cbaf64d3dbdd635153148a7f544a01fa209423 Mon Sep 17 00:00:00 2001 From: Nelson J Morais Date: Thu, 22 Oct 2020 18:36:16 +0100 Subject: [PATCH 21/23] x.py test --test-args flag description enhancement --- src/bootstrap/flags.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 22cfd0c56431d..3834e50e3fa11 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -232,7 +232,13 @@ To learn more about a subcommand, run `./x.py -h`", match subcommand.as_str() { "test" | "t" => { opts.optflag("", "no-fail-fast", "Run all tests regardless of failure"); - opts.optmulti("", "test-args", "extra arguments", "ARGS"); + opts.optmulti( + "", + "test-args", + "extra arguments to be passed for the test tool being used \ + (e.g. libtest, compiletest or rustdoc)", + "ARGS", + ); opts.optmulti( "", "rustc-args", From 929f80ece9d8875ef38dc45b4cfe372f263bc7c2 Mon Sep 17 00:00:00 2001 From: Nicolas Nattis Date: Sat, 12 Sep 2020 13:53:30 -0300 Subject: [PATCH 22/23] Add a spin loop hint for Arc::downgrade --- library/alloc/src/lib.rs | 1 + library/alloc/src/sync.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index b69e19072af44..c039be8f67cda 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -118,6 +118,7 @@ #![feature(raw_ref_op)] #![feature(rustc_attrs)] #![feature(receiver_trait)] +#![feature(renamed_spin_loop)] #![feature(min_specialization)] #![feature(slice_ptr_get)] #![feature(slice_ptr_len)] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 3a83aa7cbe5bd..cd18535b0697d 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -10,6 +10,7 @@ use core::cmp::Ordering; use core::convert::{From, TryFrom}; use core::fmt; use core::hash::{Hash, Hasher}; +use core::hint; use core::intrinsics::abort; use core::iter; use core::marker::{PhantomData, Unpin, Unsize}; @@ -764,6 +765,7 @@ impl Arc { loop { // check if the weak counter is currently "locked"; if so, spin. if cur == usize::MAX { + hint::spin_loop(); cur = this.inner().weak.load(Relaxed); continue; } From f3265fec7a46d2aa31df120ba737942b51579302 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 23 Oct 2020 23:52:06 +0200 Subject: [PATCH 23/23] Fix Ubuntu download URL --- src/ci/docker/host-x86_64/armhf-gnu/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile index 9fb5faf3ee0f4..9370f5debb5ea 100644 --- a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile @@ -58,7 +58,7 @@ RUN curl https://www.busybox.net/downloads/busybox-1.21.1.tar.bz2 | tar xjf - && # Download the ubuntu rootfs, which we'll use as a chroot for all our tests. WORKDIR /tmp RUN mkdir rootfs/ubuntu -RUN curl http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04-core-armhf.tar.gz | \ +RUN curl http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04.6-base-armhf.tar.gz | \ tar xzf - -C rootfs/ubuntu && \ cd rootfs && mkdir proc sys dev etc etc/init.d