Auto merge of #67342 - Centril:rollup-fl44n41, r=Centril

Rollup of 7 pull requests

Successful merges:

 - #65778 (Stabilize `std::{rc,sync}::Weak::{weak_count, strong_count}`)
 - #66570 (stabilize Result::map_or)
 - #66735 (Add str::strip_prefix and str::strip_suffix)
 - #66771 (Stabilize the `core::panic` module)
 - #67317 (fix type_name_of_val doc comment)
 - #67324 (Fix repetition in matches/mod.rs)
 - #67325 (cleanup with push_fake_read)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-12-16 12:10:59 +00:00
commit f0d4b57193
14 changed files with 146 additions and 114 deletions

View File

@ -1836,7 +1836,7 @@ impl<T: ?Sized> Weak<T> {
/// 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<T: ?Sized> Weak<T> {
/// 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<usize> {
/// 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`

View File

@ -114,28 +114,28 @@ fn test_weak_count() {
#[test]
fn weak_counts() {
assert_eq!(Weak::weak_count(&Weak::<u64>::new()), None);
assert_eq!(Weak::weak_count(&Weak::<u64>::new()), 0);
assert_eq!(Weak::strong_count(&Weak::<u64>::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);
}

View File

@ -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<T: ?Sized> Weak<T> {
/// 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<T: ?Sized> Weak<T> {
/// 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<T: ?Sized> Weak<T> {
/// `Weak`s pointing to the same allocation.
///
/// [`Weak::new`]: #method.new
#[unstable(feature = "weak_counts", issue = "57977")]
pub fn weak_count(&self) -> Option<usize> {
// 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`,

View File

@ -62,28 +62,28 @@ fn test_arc_get_mut() {
#[test]
fn weak_counts() {
assert_eq!(Weak::weak_count(&Weak::<u64>::new()), None);
assert_eq!(Weak::weak_count(&Weak::<u64>::new()), 0);
assert_eq!(Weak::strong_count(&Weak::<u64>::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);
}

View File

@ -476,7 +476,7 @@ pub const fn type_name<T: ?Sized>() -> &'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::<Option<String>>(None)` could return the
/// type. For example, `type_name_of::<Option<String>>(None)` could return
/// `"Option<String>"` or `"std::option::Option<std::string::String>"`, but not
/// `"foobar"`. In addition, the output may change between versions of the
/// compiler.

View File

@ -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
}

View File

@ -520,7 +520,6 @@ impl<T, E> Result<T, E> {
/// # 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<T, E> Result<T, E> {
/// 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, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
match self {
Ok(t) => f(t),

View File

@ -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>,
<P as 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.
///

View File

@ -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,

View File

@ -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<Local>,
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));
}
}
}

View File

@ -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,

View File

@ -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,

View File

@ -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))

View File

@ -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 {