From 16e10bf81ee73f61cf813acef3d5dbbce4f66da2 Mon Sep 17 00:00:00 2001 From: Francesca Lovebloom Date: Wed, 7 Oct 2020 15:46:05 -0700 Subject: [PATCH 01/25] 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 e34277d5af0..1b17c2c278f 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/25] 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 4423cfc27dd..1da186d9fbb 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/25] 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 1da186d9fbb..084ddffab0b 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -495,7 +495,7 @@ pub fn contains(&self, item: &U) -> bool 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 @@ fn start_bound(&self) -> Bound<&T> { 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/25] 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 5f63c03993d..a9a45e61a38 100644 --- a/compiler/rustc_mir/src/transform/simplify_branches.rs +++ b/compiler/rustc_mir/src/transform/simplify_branches.rs @@ -49,9 +49,10 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } 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/25] 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 ed8ee2d8823..834dd4656ff 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -529,6 +529,13 @@ fn test_slice_fail() { 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 @@ fn test_slice_fail() { } } + 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 084ddffab0b..1d67e65e51f 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -446,6 +446,20 @@ pub fn into_inner(self) -> (Idx, Idx) { } } +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 f1f21c1d24b..660c8a2da5d 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 @@ fn index(self, slice: &[T]) -> &[T] { 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 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] { 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 4f8aa246e52..f3635414311 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 ac5c9353ccb..9ccc5a08dcb 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -1341,6 +1341,14 @@ fn simple() { 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 @@ fn simple() { } } + 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/25] 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 4d884dde393..cf5e99845d1 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 @@ fn unify_values(value1: &Self, value2: &Self) -> Result { // 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 e84ff8baeea..63facbf3b8c 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/25] 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 00000000000..00e1c79ca3f --- /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/25] 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 00000000000..7b32a33ea4f --- /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/25] 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 cf5e99845d1..16e9aafb25a 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -175,19 +175,15 @@ fn tag() -> &'static str { 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 @@ fn unify_values(value1: &Self, value2: &Self) -> Result { // 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 9b90e1762e6cb21baa504a27530b9aa404fbe3ac Mon Sep 17 00:00:00 2001 From: Canop Date: Thu, 1 Oct 2020 11:13:38 +0200 Subject: [PATCH 10/25] 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 825144e5a6f..394be746ec2 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -562,6 +562,52 @@ pub fn ok_or_else E>(self, err: F) -> Result { } } + ///////////////////////////////////////////////////////////////////////// + // 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 11/25] 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 394be746ec2..64541da300e 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -581,25 +581,7 @@ pub fn ok_or_else E>(self, err: F) -> Result { #[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 12/25] 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 64541da300e..65575f4c41b 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -574,17 +574,22 @@ pub fn ok_or_else E>(self, err: F) -> Result { /// ``` /// #![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 @@ pub fn xor(self, optb: Option) -> 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 @@ pub fn get_or_insert_with T>(&mut self, f: F) -> &mut T { *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 13/25] 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 65575f4c41b..8fd3bfe77b8 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -566,8 +566,7 @@ pub fn ok_or_else E>(self, err: F) -> Result { // 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 @@ pub fn ok_or_else E>(self, err: F) -> Result { /// ``` #[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 @@ pub fn xor(self, optb: Option) -> 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 @@ pub fn xor(self, optb: Option) -> 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 14/25] 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 8fd3bfe77b8..4e8a74d9162 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -568,6 +568,8 @@ pub fn ok_or_else E>(self, err: F) -> Result { /// 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 15/25] 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 4e8a74d9162..a3d20f016fd 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -562,10 +562,6 @@ pub fn ok_or_else E>(self, err: F) -> Result { } } - ///////////////////////////////////////////////////////////////////////// - // 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 16/25] 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 a3d20f016fd..3daf26208b9 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -581,7 +581,7 @@ pub fn ok_or_else E>(self, err: F) -> Result { /// 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 17/25] 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 a4bbb18da59..9b704ee9eca 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 18/25] 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 5524d91a6d5..0e5e22dcaae 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 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { 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 @@ fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> bool { _ => 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 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool { 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 @@ fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool { 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 d9ec6bb20fd..53521d0e9f3 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -1040,16 +1040,6 @@ fn has_type_flags(&self, flags: ty::TypeFlags) -> bool { } } -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 19/25] 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 a027d6845ea..ef734f260af 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 a7bc1a2edf6066c16b01f40a2a0120c9d6ff4a49 Mon Sep 17 00:00:00 2001 From: Rich Kadel Date: Fri, 23 Oct 2020 11:41:56 -0700 Subject: [PATCH 20/25] Make codegen coverage_context optional, and check Addresses Issue #78286 Libraries compiled with coverage and linked with out enabling coverage would fail when attempting to add the library's coverage statements to the codegen coverage context (None). Now, if coverage statements are encountered while compiling / linking with `-Z instrument-coverage` disabled, codegen will *not* attempt to add code regions to a coverage map, and it will not inject the LLVM instrprof_increment intrinsic calls. --- compiler/rustc_codegen_llvm/src/context.rs | 4 +- .../src/coverageinfo/mapgen.rs | 5 +- .../src/coverageinfo/mod.rs | 79 +++++++++++-------- .../rustc_codegen_ssa/src/mir/coverageinfo.rs | 24 +++--- .../src/traits/coverageinfo.rs | 12 ++- 5 files changed, 74 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 150cedde7e8..56ff580b43b 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -324,8 +324,8 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { } #[inline] - pub fn coverage_context(&'a self) -> &'a coverageinfo::CrateCoverageContext<'tcx> { - self.coverage_cx.as_ref().unwrap() + pub fn coverage_context(&'a self) -> Option<&'a coverageinfo::CrateCoverageContext<'tcx>> { + self.coverage_cx.as_ref() } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 0098555a373..94ef33ac5b4 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -26,7 +26,10 @@ /// undocumented details in Clang's implementation (that may or may not be important) were also /// replicated for Rust's Coverage Map. pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { - let function_coverage_map = cx.coverage_context().take_function_coverage_map(); + if cx.coverage_context().is_none() { + return; + } + let function_coverage_map = cx.coverage_context().unwrap().take_function_coverage_map(); if function_coverage_map.is_empty() { // This module has no functions with coverage instrumentation return; diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 2bd37bf9c4f..7fdbe1a5512 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -64,17 +64,22 @@ fn add_counter_region( function_source_hash: u64, id: CounterValueReference, region: CodeRegion, - ) { - debug!( - "adding counter to coverage_regions: instance={:?}, function_source_hash={}, id={:?}, \ - at {:?}", - instance, function_source_hash, id, region, - ); - let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut(); - coverage_regions - .entry(instance) - .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) - .add_counter(function_source_hash, id, region); + ) -> bool { + if let Some(coverage_context) = self.coverage_context() { + debug!( + "adding counter to coverage_regions: instance={:?}, function_source_hash={}, id={:?}, \ + at {:?}", + instance, function_source_hash, id, region, + ); + let mut coverage_regions = coverage_context.function_coverage_map.borrow_mut(); + coverage_regions + .entry(instance) + .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) + .add_counter(function_source_hash, id, region); + true + } else { + false + } } fn add_counter_expression_region( @@ -85,29 +90,39 @@ fn add_counter_expression_region( op: Op, rhs: ExpressionOperandId, region: CodeRegion, - ) { - debug!( - "adding counter expression to coverage_regions: instance={:?}, id={:?}, {:?} {:?} {:?}, \ - at {:?}", - instance, id, lhs, op, rhs, region, - ); - let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut(); - coverage_regions - .entry(instance) - .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) - .add_counter_expression(id, lhs, op, rhs, region); + ) -> bool { + if let Some(coverage_context) = self.coverage_context() { + debug!( + "adding counter expression to coverage_regions: instance={:?}, id={:?}, {:?} {:?} {:?}, \ + at {:?}", + instance, id, lhs, op, rhs, region, + ); + let mut coverage_regions = coverage_context.function_coverage_map.borrow_mut(); + coverage_regions + .entry(instance) + .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) + .add_counter_expression(id, lhs, op, rhs, region); + true + } else { + false + } } - fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: CodeRegion) { - debug!( - "adding unreachable code to coverage_regions: instance={:?}, at {:?}", - instance, region, - ); - let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut(); - coverage_regions - .entry(instance) - .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) - .add_unreachable_region(region); + fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool { + if let Some(coverage_context) = self.coverage_context() { + debug!( + "adding unreachable code to coverage_regions: instance={:?}, at {:?}", + instance, region, + ); + let mut coverage_regions = coverage_context.function_coverage_map.borrow_mut(); + coverage_regions + .entry(instance) + .or_insert_with(|| FunctionCoverage::new(self.tcx, instance)) + .add_unreachable_region(region); + true + } else { + false + } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs index a2ad27b925c..4811adea9ec 100644 --- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs @@ -10,19 +10,19 @@ pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage) { let Coverage { kind, code_region } = coverage; match kind { CoverageKind::Counter { function_source_hash, id } => { - bx.add_counter_region(self.instance, function_source_hash, id, code_region); + if bx.add_counter_region(self.instance, function_source_hash, id, code_region) { + let coverageinfo = bx.tcx().coverageinfo(self.instance.def_id()); - let coverageinfo = bx.tcx().coverageinfo(self.instance.def_id()); - - let fn_name = bx.create_pgo_func_name_var(self.instance); - let hash = bx.const_u64(function_source_hash); - let num_counters = bx.const_u32(coverageinfo.num_counters); - let id = bx.const_u32(u32::from(id)); - debug!( - "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", - fn_name, hash, num_counters, id, - ); - bx.instrprof_increment(fn_name, hash, num_counters, id); + let fn_name = bx.create_pgo_func_name_var(self.instance); + let hash = bx.const_u64(function_source_hash); + let num_counters = bx.const_u32(coverageinfo.num_counters); + let id = bx.const_u32(u32::from(id)); + debug!( + "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", + fn_name, hash, num_counters, id, + ); + bx.instrprof_increment(fn_name, hash, num_counters, id); + } } CoverageKind::Expression { id, lhs, op, rhs } => { bx.add_counter_expression_region(self.instance, id, lhs, op, rhs, code_region); diff --git a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs index b74e4e45901..3b1654f3ad4 100644 --- a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs @@ -9,14 +9,18 @@ pub trait CoverageInfoMethods: BackendTypes { pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { fn create_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value; + /// Returns true if the counter was added to the coverage map; false if `-Z instrument-coverage` + /// is not enabled (a coverage map is not being generated). fn add_counter_region( &mut self, instance: Instance<'tcx>, function_source_hash: u64, id: CounterValueReference, region: CodeRegion, - ); + ) -> bool; + /// Returns true if the expression was added to the coverage map; false if + /// `-Z instrument-coverage` is not enabled (a coverage map is not being generated). fn add_counter_expression_region( &mut self, instance: Instance<'tcx>, @@ -25,7 +29,9 @@ fn add_counter_expression_region( op: Op, rhs: ExpressionOperandId, region: CodeRegion, - ); + ) -> bool; - fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: CodeRegion); + /// Returns true if the region was added to the coverage map; false if `-Z instrument-coverage` + /// is not enabled (a coverage map is not being generated). + fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool; } 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/25] 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 22cfd0c5643..3834e50e3fa 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -232,7 +232,13 @@ pub fn parse(args: &[String]) -> Flags { 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/25] 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 b69e19072af..c039be8f67c 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 3a83aa7cbe5..cd18535b069 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -10,6 +10,7 @@ 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 @@ pub fn downgrade(this: &Self) -> Weak { 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 6640a62e0e9d14f521fcfed5edb001968f7c6f63 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 23 Oct 2020 12:54:00 -0700 Subject: [PATCH 23/25] Revert "Set .llvmbc and .llvmcmd sections as allocatable" --- compiler/rustc_codegen_llvm/src/back/write.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 092d1cea295..ea1a7cfa5d3 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -936,8 +936,8 @@ unsafe fn embed_bitcode( llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); } else { let asm = " - .section .llvmbc,\"a\" - .section .llvmcmd,\"a\" + .section .llvmbc,\"e\" + .section .llvmcmd,\"e\" "; llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); } From f75a236fe0751a0d9bfb740c32eec14da787f112 Mon Sep 17 00:00:00 2001 From: Rich Kadel Date: Fri, 23 Oct 2020 14:58:08 -0700 Subject: [PATCH 24/25] Update compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs Co-authored-by: Wesley Wiser --- compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 94ef33ac5b4..c1163a871cf 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -26,10 +26,10 @@ /// undocumented details in Clang's implementation (that may or may not be important) were also /// replicated for Rust's Coverage Map. pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { - if cx.coverage_context().is_none() { - return; - } - let function_coverage_map = cx.coverage_context().unwrap().take_function_coverage_map(); + let function_coverage_map = match cx.coverage_context() { + Some(ctx) => ctx.take_function_coverage_map(), + None => return, + }; if function_coverage_map.is_empty() { // This module has no functions with coverage instrumentation return; From f88d6e8437fdf4284ca7a1548e2e5ecfe89585be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 23 Oct 2020 18:11:52 +0200 Subject: [PATCH 25/25] Loop instead of recursion --- compiler/rustc_ast_lowering/src/pat.rs | 150 +++++++++++++------------ 1 file changed, 79 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index cb7b7c0eb61..a1cbcde1f42 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -10,82 +10,90 @@ use rustc_span::{source_map::Spanned, Span}; impl<'a, 'hir> LoweringContext<'a, 'hir> { - crate fn lower_pat(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> { + crate fn lower_pat(&mut self, mut pattern: &Pat) -> &'hir hir::Pat<'hir> { ensure_sufficient_stack(|| { - let node = match p.kind { - PatKind::Wild => hir::PatKind::Wild, - PatKind::Ident(ref binding_mode, ident, ref sub) => { - let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s)); - let node = self.lower_pat_ident(p, binding_mode, ident, lower_sub); - node - } - PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)), - PatKind::TupleStruct(ref path, ref pats) => { - let qpath = self.lower_qpath( - p.id, - &None, - path, - ParamMode::Optional, - ImplTraitContext::disallowed(), - ); - let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); - hir::PatKind::TupleStruct(qpath, pats, ddpos) - } - PatKind::Or(ref pats) => hir::PatKind::Or( - self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat(x))), - ), - PatKind::Path(ref qself, ref path) => { - let qpath = self.lower_qpath( - p.id, - qself, - path, - ParamMode::Optional, - ImplTraitContext::disallowed(), - ); - hir::PatKind::Path(qpath) - } - PatKind::Struct(ref path, ref fields, etc) => { - let qpath = self.lower_qpath( - p.id, - &None, - path, - ParamMode::Optional, - ImplTraitContext::disallowed(), - ); + // loop here to avoid recursion + let node = loop { + match pattern.kind { + PatKind::Wild => break hir::PatKind::Wild, + PatKind::Ident(ref binding_mode, ident, ref sub) => { + let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s)); + break self.lower_pat_ident(pattern, binding_mode, ident, lower_sub); + } + PatKind::Lit(ref e) => break hir::PatKind::Lit(self.lower_expr(e)), + PatKind::TupleStruct(ref path, ref pats) => { + let qpath = self.lower_qpath( + pattern.id, + &None, + path, + ParamMode::Optional, + ImplTraitContext::disallowed(), + ); + let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); + break hir::PatKind::TupleStruct(qpath, pats, ddpos); + } + PatKind::Or(ref pats) => { + break hir::PatKind::Or( + self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat(x))), + ); + } + PatKind::Path(ref qself, ref path) => { + let qpath = self.lower_qpath( + pattern.id, + qself, + path, + ParamMode::Optional, + ImplTraitContext::disallowed(), + ); + break hir::PatKind::Path(qpath); + } + PatKind::Struct(ref path, ref fields, etc) => { + let qpath = self.lower_qpath( + pattern.id, + &None, + path, + ParamMode::Optional, + ImplTraitContext::disallowed(), + ); - let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::FieldPat { - hir_id: self.next_id(), - ident: f.ident, - pat: self.lower_pat(&f.pat), - is_shorthand: f.is_shorthand, - span: f.span, - })); - hir::PatKind::Struct(qpath, fs, etc) + let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::FieldPat { + hir_id: self.next_id(), + ident: f.ident, + pat: self.lower_pat(&f.pat), + is_shorthand: f.is_shorthand, + span: f.span, + })); + break hir::PatKind::Struct(qpath, fs, etc); + } + PatKind::Tuple(ref pats) => { + let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple"); + break hir::PatKind::Tuple(pats, ddpos); + } + PatKind::Box(ref inner) => { + break hir::PatKind::Box(self.lower_pat(inner)); + } + PatKind::Ref(ref inner, mutbl) => { + break hir::PatKind::Ref(self.lower_pat(inner), mutbl); + } + PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => { + break hir::PatKind::Range( + e1.as_deref().map(|e| self.lower_expr(e)), + e2.as_deref().map(|e| self.lower_expr(e)), + self.lower_range_end(end, e2.is_some()), + ); + } + PatKind::Slice(ref pats) => break self.lower_pat_slice(pats), + PatKind::Rest => { + // If we reach here the `..` pattern is not semantically allowed. + break self.ban_illegal_rest_pat(pattern.span); + } + // return inner to be processed in next loop + PatKind::Paren(ref inner) => pattern = inner, + PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span), } - PatKind::Tuple(ref pats) => { - let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple"); - hir::PatKind::Tuple(pats, ddpos) - } - PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)), - PatKind::Ref(ref inner, mutbl) => hir::PatKind::Ref(self.lower_pat(inner), mutbl), - PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => { - hir::PatKind::Range( - e1.as_deref().map(|e| self.lower_expr(e)), - e2.as_deref().map(|e| self.lower_expr(e)), - self.lower_range_end(end, e2.is_some()), - ) - } - PatKind::Slice(ref pats) => self.lower_pat_slice(pats), - PatKind::Rest => { - // If we reach here the `..` pattern is not semantically allowed. - self.ban_illegal_rest_pat(p.span) - } - // FIXME: consider not using recursion to lower this. - PatKind::Paren(ref inner) => return self.lower_pat(inner), - PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", p.span), }; - self.pat_with_node_id_of(p, node) + self.pat_with_node_id_of(pattern, node) }) }