diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 1ff1c3c834f4e..42a278de98bef 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -1836,7 +1836,7 @@ impl Weak { /// If `self` was created using [`Weak::new`], this will return 0. /// /// [`Weak::new`]: #method.new - #[unstable(feature = "weak_counts", issue = "57977")] + #[stable(feature = "weak_counts", since = "1.41.0")] pub fn strong_count(&self) -> usize { if let Some(inner) = self.inner() { inner.strong() @@ -1847,20 +1847,16 @@ impl Weak { /// Gets the number of `Weak` pointers pointing to this allocation. /// - /// If `self` was created using [`Weak::new`], this will return `None`. If - /// not, the returned value is at least 1, since `self` still points to the - /// allocation. - /// - /// [`Weak::new`]: #method.new - #[unstable(feature = "weak_counts", issue = "57977")] - pub fn weak_count(&self) -> Option { + /// If no strong pointers remain, this will return zero. + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn weak_count(&self) -> usize { self.inner().map(|inner| { if inner.strong() > 0 { inner.weak() - 1 // subtract the implicit weak ptr } else { - inner.weak() + 0 } - }) + }).unwrap_or(0) } /// Returns `None` when the pointer is dangling and there is no allocated `RcBox` diff --git a/src/liballoc/rc/tests.rs b/src/liballoc/rc/tests.rs index 6fd3f90935714..bf5c85a5c5960 100644 --- a/src/liballoc/rc/tests.rs +++ b/src/liballoc/rc/tests.rs @@ -114,28 +114,28 @@ fn test_weak_count() { #[test] fn weak_counts() { - assert_eq!(Weak::weak_count(&Weak::::new()), None); + assert_eq!(Weak::weak_count(&Weak::::new()), 0); assert_eq!(Weak::strong_count(&Weak::::new()), 0); let a = Rc::new(0); let w = Rc::downgrade(&a); assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), Some(1)); + assert_eq!(Weak::weak_count(&w), 1); let w2 = w.clone(); assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), Some(2)); + assert_eq!(Weak::weak_count(&w), 2); assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), Some(2)); + assert_eq!(Weak::weak_count(&w2), 2); drop(w); assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), Some(1)); + assert_eq!(Weak::weak_count(&w2), 1); let a2 = a.clone(); assert_eq!(Weak::strong_count(&w2), 2); - assert_eq!(Weak::weak_count(&w2), Some(1)); + assert_eq!(Weak::weak_count(&w2), 1); drop(a2); drop(a); assert_eq!(Weak::strong_count(&w2), 0); - assert_eq!(Weak::weak_count(&w2), Some(1)); + assert_eq!(Weak::weak_count(&w2), 0); drop(w2); } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 19b0086fa333c..a99564c0dac8a 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -12,7 +12,7 @@ use core::sync::atomic; use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; use core::borrow; use core::fmt; -use core::cmp::{self, Ordering}; +use core::cmp::Ordering; use core::iter; use core::intrinsics::abort; use core::mem::{self, align_of, align_of_val, size_of_val}; @@ -1529,7 +1529,7 @@ impl Weak { /// If `self` was created using [`Weak::new`], this will return 0. /// /// [`Weak::new`]: #method.new - #[unstable(feature = "weak_counts", issue = "57977")] + #[stable(feature = "weak_counts", since = "1.41.0")] pub fn strong_count(&self) -> usize { if let Some(inner) = self.inner() { inner.strong.load(SeqCst) @@ -1541,9 +1541,8 @@ impl Weak { /// Gets an approximation of the number of `Weak` pointers pointing to this /// allocation. /// - /// If `self` was created using [`Weak::new`], this will return 0. If not, - /// the returned value is at least 1, since `self` still points to the - /// allocation. + /// If `self` was created using [`Weak::new`], or if there are no remaining + /// strong pointers, this will return 0. /// /// # Accuracy /// @@ -1552,31 +1551,22 @@ impl Weak { /// `Weak`s pointing to the same allocation. /// /// [`Weak::new`]: #method.new - #[unstable(feature = "weak_counts", issue = "57977")] - pub fn weak_count(&self) -> Option { - // Due to the implicit weak pointer added when any strong pointers are - // around, we cannot implement `weak_count` correctly since it - // necessarily requires accessing the strong count and weak count in an - // unsynchronized fashion. So this version is a bit racy. + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn weak_count(&self) -> usize { self.inner().map(|inner| { - let strong = inner.strong.load(SeqCst); let weak = inner.weak.load(SeqCst); + let strong = inner.strong.load(SeqCst); if strong == 0 { - // If the last `Arc` has *just* been dropped, it might not yet - // have removed the implicit weak count, so the value we get - // here might be 1 too high. - weak + 0 } else { - // As long as there's still at least 1 `Arc` around, subtract - // the implicit weak pointer. - // Note that the last `Arc` might get dropped between the 2 - // loads we do above, removing the implicit weak pointer. This - // means that the value might be 1 too low here. In order to not - // return 0 here (which would happen if we're the only weak - // pointer), we guard against that specifically. - cmp::max(1, weak - 1) + // Since we observed that there was at least one strong pointer + // after reading the weak count, we know that the implicit weak + // reference (present whenever any strong references are alive) + // was still around when we observed the weak count, and can + // therefore safely subtract it. + weak - 1 } - }) + }).unwrap_or(0) } /// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`, diff --git a/src/liballoc/sync/tests.rs b/src/liballoc/sync/tests.rs index 9ddba495b7e78..8f516129cd00f 100644 --- a/src/liballoc/sync/tests.rs +++ b/src/liballoc/sync/tests.rs @@ -62,28 +62,28 @@ fn test_arc_get_mut() { #[test] fn weak_counts() { - assert_eq!(Weak::weak_count(&Weak::::new()), None); + assert_eq!(Weak::weak_count(&Weak::::new()), 0); assert_eq!(Weak::strong_count(&Weak::::new()), 0); let a = Arc::new(0); let w = Arc::downgrade(&a); assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), Some(1)); + assert_eq!(Weak::weak_count(&w), 1); let w2 = w.clone(); assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), Some(2)); + assert_eq!(Weak::weak_count(&w), 2); assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), Some(2)); + assert_eq!(Weak::weak_count(&w2), 2); drop(w); assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), Some(1)); + assert_eq!(Weak::weak_count(&w2), 1); let a2 = a.clone(); assert_eq!(Weak::strong_count(&w2), 2); - assert_eq!(Weak::weak_count(&w2), Some(1)); + assert_eq!(Weak::weak_count(&w2), 1); drop(a2); drop(a); assert_eq!(Weak::strong_count(&w2), 0); - assert_eq!(Weak::weak_count(&w2), Some(1)); + assert_eq!(Weak::weak_count(&w2), 0); drop(w2); } diff --git a/src/libcore/any.rs b/src/libcore/any.rs index b0e3021e0bf4d..7935c9b1b392d 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -476,7 +476,7 @@ pub const fn type_name() -> &'static str { /// /// This is intended for diagnostic use. The exact contents and format of the /// string are not specified, other than being a best-effort description of the -/// type. For example, `type_name_of::>(None)` could return the +/// type. For example, `type_name_of::>(None)` could return /// `"Option"` or `"std::option::Option"`, but not /// `"foobar"`. In addition, the output may change between versions of the /// compiler. diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index e924ee2036988..48bb504a73c34 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -1,8 +1,6 @@ //! Panic support in the standard library. -#![unstable(feature = "core_panic_info", - reason = "newly available in libcore", - issue = "44489")] +#![stable(feature = "core_panic_info", since = "1.41.0")] use crate::any::Any; use crate::fmt; @@ -39,10 +37,10 @@ pub struct PanicInfo<'a> { } impl<'a> PanicInfo<'a> { - #![unstable(feature = "panic_internals", - reason = "internal details of the implementation of the `panic!` \ - and related macros", - issue = "0")] + #[unstable(feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` \ + and related macros", + issue = "0")] #[doc(hidden)] #[inline] pub fn internal_constructor( @@ -57,6 +55,10 @@ impl<'a> PanicInfo<'a> { } } + #[unstable(feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` \ + and related macros", + issue = "0")] #[doc(hidden)] #[inline] pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) { @@ -90,7 +92,7 @@ impl<'a> PanicInfo<'a> { /// returns that message ready to be used for example with [`fmt::write`] /// /// [`fmt::write`]: ../fmt/fn.write.html - #[unstable(feature = "panic_info_message", issue = "44489")] + #[unstable(feature = "panic_info_message", issue = "66745")] pub fn message(&self) -> Option<&fmt::Arguments<'_>> { self.message } diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 1a0845f3a6dda..fb4dc62d8c176 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -520,7 +520,6 @@ impl Result { /// # Examples /// /// ``` - /// #![feature(result_map_or)] /// let x: Result<_, &str> = Ok("foo"); /// assert_eq!(x.map_or(42, |v| v.len()), 3); /// @@ -528,7 +527,7 @@ impl Result { /// assert_eq!(x.map_or(42, |v| v.len()), 42); /// ``` #[inline] - #[unstable(feature = "result_map_or", issue = "66293")] + #[stable(feature = "result_map_or", since = "1.41.0")] pub fn map_or U>(self, default: U, f: F) -> U { match self { Ok(t) => f(t), diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 6d225a25f20ab..763714e536edc 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -8,7 +8,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use self::pattern::Pattern; -use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; +use self::pattern::{Searcher, SearchStep, ReverseSearcher, DoubleEndedSearcher}; use crate::char; use crate::fmt::{self, Write}; @@ -3798,6 +3798,77 @@ impl str { } } + /// Returns a string slice with the prefix removed. + /// + /// If the string starts with the pattern `prefix`, `Some` is returned with the substring where + /// the prefix is removed. Unlike `trim_start_matches`, this method removes the prefix exactly + /// once. + /// + /// If the string does not start with `prefix`, `None` is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_strip)] + /// + /// assert_eq!("foobar".strip_prefix("foo"), Some("bar")); + /// assert_eq!("foobar".strip_prefix("bar"), None); + /// assert_eq!("foofoo".strip_prefix("foo"), Some("foo")); + /// ``` + #[must_use = "this returns the remaining substring as a new slice, \ + without modifying the original"] + #[unstable(feature = "str_strip", reason = "newly added", issue = "67302")] + pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a str> { + let mut matcher = prefix.into_searcher(self); + if let SearchStep::Match(start, len) = matcher.next() { + debug_assert_eq!(start, 0, "The first search step from Searcher \ + must include the first character"); + unsafe { + // Searcher is known to return valid indices. + Some(self.get_unchecked(len..)) + } + } else { + None + } + } + + /// Returns a string slice with the suffix removed. + /// + /// If the string ends with the pattern `suffix`, `Some` is returned with the substring where + /// the suffix is removed. Unlike `trim_end_matches`, this method removes the suffix exactly + /// once. + /// + /// If the string does not end with `suffix`, `None` is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_strip)] + /// assert_eq!("barfoo".strip_suffix("foo"), Some("bar")); + /// assert_eq!("barfoo".strip_suffix("bar"), None); + /// assert_eq!("foofoo".strip_suffix("foo"), Some("foo")); + /// ``` + #[must_use = "this returns the remaining substring as a new slice, \ + without modifying the original"] + #[unstable(feature = "str_strip", reason = "newly added", issue = "67302")] + pub fn strip_suffix<'a, P>(&'a self, suffix: P) -> Option<&'a str> + where + P: Pattern<'a>, +

>::Searcher: ReverseSearcher<'a>, + { + let mut matcher = suffix.into_searcher(self); + if let SearchStep::Match(start, end) = matcher.next_back() { + debug_assert_eq!(end, self.len(), "The first search step from ReverseSearcher \ + must include the last character"); + unsafe { + // Searcher is known to return valid indices. + Some(self.get_unchecked(..start)) + } + } else { + None + } + } + /// Returns a string slice with all suffixes that match a pattern /// repeatedly removed. /// diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 3ed6b4ff34678..6bd8d2f7c0792 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -59,6 +59,18 @@ impl<'tcx> CFG<'tcx> { )); } + pub fn push_fake_read( + &mut self, + block: BasicBlock, + source_info: SourceInfo, + cause: FakeReadCause, + place: Place<'tcx>, + ) { + let kind = StatementKind::FakeRead(cause, box place); + let stmt = Statement { source_info, kind }; + self.push(block, stmt); + } + pub fn terminate(&mut self, block: BasicBlock, source_info: SourceInfo, diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index f66f1cb73666a..ddacda72e1e65 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -484,7 +484,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn read_fake_borrows( &mut self, - block: BasicBlock, + bb: BasicBlock, fake_borrow_temps: &mut Vec, source_info: SourceInfo, ) { @@ -492,16 +492,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // fake borrows so that they are live across those index // expressions. for temp in fake_borrow_temps { - self.cfg.push( - block, - Statement { - source_info, - kind: StatementKind::FakeRead( - FakeReadCause::ForIndex, - Box::new(Place::from(*temp)), - ) - } - ); + self.cfg.push_fake_read(bb, source_info, FakeReadCause::ForIndex, Place::from(*temp)); } } } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 032ea7d8161cb..bf0b2439c00b5 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -69,8 +69,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// 3. Create the decision tree and record the places that we bind or test. /// 4. Determine the fake borrows that are needed from the above places. /// Create the required temporaries for them. - /// 5. Create everything else: Create everything else: the guards and the - /// arms. + /// 5. Create everything else: the guards and the arms. /// /// ## Fake Reads and borrows /// @@ -132,13 +131,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // check safety. let source_info = self.source_info(scrutinee_span); - self.cfg.push(block, Statement { - source_info, - kind: StatementKind::FakeRead( - FakeReadCause::ForMatchedPlace, - box(scrutinee_place.clone()), - ), - }); + let cause_matched_place = FakeReadCause::ForMatchedPlace; + self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place.clone()); // Step 2. Create the otherwise and prebinding blocks. @@ -314,16 +308,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard); unpack!(block = self.into(&place, block, initializer)); - // Inject a fake read, see comments on `FakeReadCause::ForLet`. let source_info = self.source_info(irrefutable_pat.span); - self.cfg.push( - block, - Statement { - source_info, - kind: StatementKind::FakeRead(FakeReadCause::ForLet, box(place)), - }, - ); + self.cfg.push_fake_read(block, source_info, FakeReadCause::ForLet, place); self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() @@ -359,13 +346,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Inject a fake read, see comments on `FakeReadCause::ForLet`. let pattern_source_info = self.source_info(irrefutable_pat.span); - self.cfg.push( - block, - Statement { - source_info: pattern_source_info, - kind: StatementKind::FakeRead(FakeReadCause::ForLet, box(place.clone())), - }, - ); + let cause_let = FakeReadCause::ForLet; + self.cfg.push_fake_read(block, pattern_source_info, cause_let, place.clone()); let ty_source_info = self.source_info(user_ty_span); let user_ty = pat_ascription_ty.user_ty( @@ -1516,13 +1498,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); for &(_, temp) in fake_borrows { - self.cfg.push(post_guard_block, Statement { - source_info: guard_end, - kind: StatementKind::FakeRead( - FakeReadCause::ForMatchGuard, - box(Place::from(temp)), - ), - }); + let cause = FakeReadCause::ForMatchGuard; + self.cfg.push_fake_read(post_guard_block, guard_end, cause, Place::from(temp)); } self.exit_scope( @@ -1565,14 +1542,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // place they refer to can't be modified by the guard. for binding in by_value_bindings.clone() { let local_id = self.var_local_id(binding.var_id, RefWithinGuard); - let place = Place::from(local_id); - self.cfg.push( - post_guard_block, - Statement { - source_info: guard_end, - kind: StatementKind::FakeRead(FakeReadCause::ForGuardBinding, box(place)), - }, - ); + let cause = FakeReadCause::ForGuardBinding; + self.cfg.push_fake_read(post_guard_block, guard_end, cause, Place::from(local_id)); } self.bind_matched_candidate_for_arm_body( post_guard_block, diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index aff91ac5af910..c4d89b1494d02 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -517,7 +517,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let left_bits = place_layout.size.bits(); let right_size = r.layout.size; let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size)); - if r_bits.ok().map_or(false, |b| b >= left_bits as u128) { + if r_bits.map_or(false, |b| b >= left_bits as u128) { let lint_root = match &self.source_scopes[source_info.scope].local_data { ClearCrossCrate::Set(data) => data.lint_root, ClearCrossCrate::Clear => return None, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 992308183b42f..880ead0e3018a 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1456,7 +1456,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { pcx.method_name = Some(method_name); pcx.assemble_inherent_candidates(); pcx.assemble_extension_candidates_for_traits_in_scope(hir::DUMMY_HIR_ID) - .ok().map_or(None, |_| { + .map_or(None, |_| { pcx.pick_core() .and_then(|pick| pick.ok()) .and_then(|pick| Some(pick.item)) diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index be90195065eb7..09bea80c95a93 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -74,7 +74,7 @@ impl TermInfo { Err(..) => return Err(Error::TermUnset), }; - if term.is_err() && env::var("MSYSCON").ok().map_or(false, |s| "mintty.exe" == s) { + if term.is_err() && env::var("MSYSCON").map_or(false, |s| "mintty.exe" == s) { // msys terminal Ok(msys_terminfo()) } else {