Auto merge of #123121 - matthiaskrgr:rollup-e4glcv3, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #122439 (match lowering: build the `Place` instead of keeping a `PlaceBuilder` around) - #122880 (Unix: Support more platforms with `preadv` and `pwritev`) - #123038 (std library thread.rs: fix NetBSD code for ILP32 CPUs.) - #123084 (`UnixStream`: override `read_buf`) - #123102 (RustWrapper: update call for llvm/llvm-project@44d037cc258dcf179d2c48…) - #123107 (Implement `Vec::pop_if`) - #123118 (Update `RwLock` deadlock example to not use shadowing) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
37f97982ca
@ -1992,7 +1992,11 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (DiagnosticHandlerCallback) {
|
if (DiagnosticHandlerCallback) {
|
||||||
|
#if LLVM_VERSION_GE(19, 0)
|
||||||
|
DiagnosticHandlerCallback(&DI, DiagnosticHandlerContext);
|
||||||
|
#else
|
||||||
DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
|
DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1111,7 +1111,10 @@ fn as_range(&self) -> Option<&'pat PatRange<'tcx>> {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct MatchPair<'pat, 'tcx> {
|
pub(crate) struct MatchPair<'pat, 'tcx> {
|
||||||
/// This place...
|
/// This place...
|
||||||
place: PlaceBuilder<'tcx>,
|
// This can be `None` if it referred to a non-captured place in a closure.
|
||||||
|
// Invariant: place.is_none() => test_case is Irrefutable
|
||||||
|
// In other words this must be `Some(_)` after simplification.
|
||||||
|
place: Option<Place<'tcx>>,
|
||||||
|
|
||||||
/// ... must pass this test...
|
/// ... must pass this test...
|
||||||
// Invariant: after creation and simplification in `Candidate::new()`, this must not be
|
// Invariant: after creation and simplification in `Candidate::new()`, this must not be
|
||||||
@ -1595,11 +1598,12 @@ fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) {
|
|||||||
fn pick_test(
|
fn pick_test(
|
||||||
&mut self,
|
&mut self,
|
||||||
candidates: &mut [&mut Candidate<'_, 'tcx>],
|
candidates: &mut [&mut Candidate<'_, 'tcx>],
|
||||||
) -> (PlaceBuilder<'tcx>, Test<'tcx>) {
|
) -> (Place<'tcx>, Test<'tcx>) {
|
||||||
// Extract the match-pair from the highest priority candidate
|
// Extract the match-pair from the highest priority candidate
|
||||||
let match_pair = &candidates.first().unwrap().match_pairs[0];
|
let match_pair = &candidates.first().unwrap().match_pairs[0];
|
||||||
let test = self.test(match_pair);
|
let test = self.test(match_pair);
|
||||||
let match_place = match_pair.place.clone();
|
// Unwrap is ok after simplification.
|
||||||
|
let match_place = match_pair.place.unwrap();
|
||||||
debug!(?test, ?match_pair);
|
debug!(?test, ?match_pair);
|
||||||
|
|
||||||
(match_place, test)
|
(match_place, test)
|
||||||
@ -1640,7 +1644,7 @@ fn pick_test(
|
|||||||
/// - candidate 1 becomes `[y @ false]` since we know that `x` was `false`.
|
/// - candidate 1 becomes `[y @ false]` since we know that `x` was `false`.
|
||||||
fn sort_candidates<'b, 'c, 'pat>(
|
fn sort_candidates<'b, 'c, 'pat>(
|
||||||
&mut self,
|
&mut self,
|
||||||
match_place: &PlaceBuilder<'tcx>,
|
match_place: Place<'tcx>,
|
||||||
test: &Test<'tcx>,
|
test: &Test<'tcx>,
|
||||||
mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
|
mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
|
||||||
) -> (
|
) -> (
|
||||||
@ -1658,7 +1662,7 @@ fn sort_candidates<'b, 'c, 'pat>(
|
|||||||
// sorting.
|
// sorting.
|
||||||
while let Some(candidate) = candidates.first_mut() {
|
while let Some(candidate) = candidates.first_mut() {
|
||||||
let Some(branch) =
|
let Some(branch) =
|
||||||
self.sort_candidate(&match_place, test, candidate, &target_candidates)
|
self.sort_candidate(match_place, test, candidate, &target_candidates)
|
||||||
else {
|
else {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
@ -1786,7 +1790,7 @@ fn test_candidates<'pat, 'b, 'c>(
|
|||||||
// For each of the N possible test outcomes, build the vector of candidates that applies if
|
// For each of the N possible test outcomes, build the vector of candidates that applies if
|
||||||
// the test has that particular outcome.
|
// the test has that particular outcome.
|
||||||
let (remaining_candidates, target_candidates) =
|
let (remaining_candidates, target_candidates) =
|
||||||
self.sort_candidates(&match_place, &test, candidates);
|
self.sort_candidates(match_place, &test, candidates);
|
||||||
|
|
||||||
// The block that we should branch to if none of the
|
// The block that we should branch to if none of the
|
||||||
// `target_candidates` match.
|
// `target_candidates` match.
|
||||||
@ -1826,7 +1830,7 @@ fn test_candidates<'pat, 'b, 'c>(
|
|||||||
scrutinee_span,
|
scrutinee_span,
|
||||||
start_block,
|
start_block,
|
||||||
remainder_start,
|
remainder_start,
|
||||||
&match_place,
|
match_place,
|
||||||
&test,
|
&test,
|
||||||
target_blocks,
|
target_blocks,
|
||||||
);
|
);
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
// identify what tests are needed, perform the tests, and then filter
|
// identify what tests are needed, perform the tests, and then filter
|
||||||
// the candidates based on the result.
|
// the candidates based on the result.
|
||||||
|
|
||||||
use crate::build::expr::as_place::PlaceBuilder;
|
|
||||||
use crate::build::matches::{Candidate, MatchPair, Test, TestBranch, TestCase, TestKind};
|
use crate::build::matches::{Candidate, MatchPair, Test, TestBranch, TestCase, TestKind};
|
||||||
use crate::build::Builder;
|
use crate::build::Builder;
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
@ -55,18 +54,17 @@ pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<
|
|||||||
Test { span: match_pair.pattern.span, kind }
|
Test { span: match_pair.pattern.span, kind }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self, target_blocks, place_builder), level = "debug")]
|
#[instrument(skip(self, target_blocks, place), level = "debug")]
|
||||||
pub(super) fn perform_test(
|
pub(super) fn perform_test(
|
||||||
&mut self,
|
&mut self,
|
||||||
match_start_span: Span,
|
match_start_span: Span,
|
||||||
scrutinee_span: Span,
|
scrutinee_span: Span,
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
otherwise_block: BasicBlock,
|
otherwise_block: BasicBlock,
|
||||||
place_builder: &PlaceBuilder<'tcx>,
|
place: Place<'tcx>,
|
||||||
test: &Test<'tcx>,
|
test: &Test<'tcx>,
|
||||||
target_blocks: FxIndexMap<TestBranch<'tcx>, BasicBlock>,
|
target_blocks: FxIndexMap<TestBranch<'tcx>, BasicBlock>,
|
||||||
) {
|
) {
|
||||||
let place = place_builder.to_place(self);
|
|
||||||
let place_ty = place.ty(&self.local_decls, self.tcx);
|
let place_ty = place.ty(&self.local_decls, self.tcx);
|
||||||
debug!(?place, ?place_ty);
|
debug!(?place, ?place_ty);
|
||||||
let target_block = |branch| target_blocks.get(&branch).copied().unwrap_or(otherwise_block);
|
let target_block = |branch| target_blocks.get(&branch).copied().unwrap_or(otherwise_block);
|
||||||
@ -475,7 +473,7 @@ fn non_scalar_compare(
|
|||||||
/// tighter match code if we do something a bit different.
|
/// tighter match code if we do something a bit different.
|
||||||
pub(super) fn sort_candidate(
|
pub(super) fn sort_candidate(
|
||||||
&mut self,
|
&mut self,
|
||||||
test_place: &PlaceBuilder<'tcx>,
|
test_place: Place<'tcx>,
|
||||||
test: &Test<'tcx>,
|
test: &Test<'tcx>,
|
||||||
candidate: &mut Candidate<'_, 'tcx>,
|
candidate: &mut Candidate<'_, 'tcx>,
|
||||||
sorted_candidates: &FxIndexMap<TestBranch<'tcx>, Vec<&mut Candidate<'_, 'tcx>>>,
|
sorted_candidates: &FxIndexMap<TestBranch<'tcx>, Vec<&mut Candidate<'_, 'tcx>>>,
|
||||||
@ -486,8 +484,11 @@ pub(super) fn sort_candidate(
|
|||||||
// than one, but it'd be very unusual to have two sides that
|
// than one, but it'd be very unusual to have two sides that
|
||||||
// both require tests; you'd expect one side to be simplified
|
// both require tests; you'd expect one side to be simplified
|
||||||
// away.)
|
// away.)
|
||||||
let (match_pair_index, match_pair) =
|
let (match_pair_index, match_pair) = candidate
|
||||||
candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == *test_place)?;
|
.match_pairs
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|&(_, mp)| mp.place == Some(test_place))?;
|
||||||
|
|
||||||
let fully_matched;
|
let fully_matched;
|
||||||
let ret = match (&test.kind, &match_pair.test_case) {
|
let ret = match (&test.kind, &match_pair.test_case) {
|
||||||
@ -521,7 +522,7 @@ pub(super) fn sort_candidate(
|
|||||||
candidate
|
candidate
|
||||||
.match_pairs
|
.match_pairs
|
||||||
.iter()
|
.iter()
|
||||||
.any(|mp| mp.place == *test_place && is_covering_range(&mp.test_case))
|
.any(|mp| mp.place == Some(test_place) && is_covering_range(&mp.test_case))
|
||||||
};
|
};
|
||||||
if sorted_candidates
|
if sorted_candidates
|
||||||
.get(&TestBranch::Failure)
|
.get(&TestBranch::Failure)
|
||||||
|
@ -95,35 +95,37 @@ pub(crate) fn false_edges(
|
|||||||
|
|
||||||
impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
||||||
pub(in crate::build) fn new(
|
pub(in crate::build) fn new(
|
||||||
mut place: PlaceBuilder<'tcx>,
|
mut place_builder: PlaceBuilder<'tcx>,
|
||||||
pattern: &'pat Pat<'tcx>,
|
pattern: &'pat Pat<'tcx>,
|
||||||
cx: &mut Builder<'_, 'tcx>,
|
cx: &mut Builder<'_, 'tcx>,
|
||||||
) -> MatchPair<'pat, 'tcx> {
|
) -> MatchPair<'pat, 'tcx> {
|
||||||
// Force the place type to the pattern's type.
|
// Force the place type to the pattern's type.
|
||||||
// FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
|
// FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
|
||||||
if let Some(resolved) = place.resolve_upvar(cx) {
|
if let Some(resolved) = place_builder.resolve_upvar(cx) {
|
||||||
place = resolved;
|
place_builder = resolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only add the OpaqueCast projection if the given place is an opaque type and the
|
// Only add the OpaqueCast projection if the given place is an opaque type and the
|
||||||
// expected type from the pattern is not.
|
// expected type from the pattern is not.
|
||||||
let may_need_cast = match place.base() {
|
let may_need_cast = match place_builder.base() {
|
||||||
PlaceBase::Local(local) => {
|
PlaceBase::Local(local) => {
|
||||||
let ty = Place::ty_from(local, place.projection(), &cx.local_decls, cx.tcx).ty;
|
let ty =
|
||||||
|
Place::ty_from(local, place_builder.projection(), &cx.local_decls, cx.tcx).ty;
|
||||||
ty != pattern.ty && ty.has_opaque_types()
|
ty != pattern.ty && ty.has_opaque_types()
|
||||||
}
|
}
|
||||||
_ => true,
|
_ => true,
|
||||||
};
|
};
|
||||||
if may_need_cast {
|
if may_need_cast {
|
||||||
place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
|
place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let place = place_builder.try_to_place(cx);
|
||||||
let default_irrefutable = || TestCase::Irrefutable { binding: None, ascription: None };
|
let default_irrefutable = || TestCase::Irrefutable { binding: None, ascription: None };
|
||||||
let mut subpairs = Vec::new();
|
let mut subpairs = Vec::new();
|
||||||
let test_case = match pattern.kind {
|
let test_case = match pattern.kind {
|
||||||
PatKind::Never | PatKind::Wild | PatKind::Error(_) => default_irrefutable(),
|
PatKind::Never | PatKind::Wild | PatKind::Error(_) => default_irrefutable(),
|
||||||
PatKind::Or { ref pats } => TestCase::Or {
|
PatKind::Or { ref pats } => TestCase::Or {
|
||||||
pats: pats.iter().map(|pat| FlatPat::new(place.clone(), pat, cx)).collect(),
|
pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(),
|
||||||
},
|
},
|
||||||
|
|
||||||
PatKind::Range(ref range) => {
|
PatKind::Range(ref range) => {
|
||||||
@ -142,13 +144,13 @@ pub(in crate::build) fn new(
|
|||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
// Apply the type ascription to the value at `match_pair.place`
|
// Apply the type ascription to the value at `match_pair.place`
|
||||||
let ascription = place.try_to_place(cx).map(|source| super::Ascription {
|
let ascription = place.map(|source| super::Ascription {
|
||||||
annotation: annotation.clone(),
|
annotation: annotation.clone(),
|
||||||
source,
|
source,
|
||||||
variance,
|
variance,
|
||||||
});
|
});
|
||||||
|
|
||||||
subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
|
subpairs.push(MatchPair::new(place_builder, subpattern, cx));
|
||||||
TestCase::Irrefutable { ascription, binding: None }
|
TestCase::Irrefutable { ascription, binding: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +163,7 @@ pub(in crate::build) fn new(
|
|||||||
ref subpattern,
|
ref subpattern,
|
||||||
is_primary: _,
|
is_primary: _,
|
||||||
} => {
|
} => {
|
||||||
let binding = place.try_to_place(cx).map(|source| super::Binding {
|
let binding = place.map(|source| super::Binding {
|
||||||
span: pattern.span,
|
span: pattern.span,
|
||||||
source,
|
source,
|
||||||
var_id: var,
|
var_id: var,
|
||||||
@ -170,14 +172,14 @@ pub(in crate::build) fn new(
|
|||||||
|
|
||||||
if let Some(subpattern) = subpattern.as_ref() {
|
if let Some(subpattern) = subpattern.as_ref() {
|
||||||
// this is the `x @ P` case; have to keep matching against `P` now
|
// this is the `x @ P` case; have to keep matching against `P` now
|
||||||
subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
|
subpairs.push(MatchPair::new(place_builder, subpattern, cx));
|
||||||
}
|
}
|
||||||
TestCase::Irrefutable { ascription: None, binding }
|
TestCase::Irrefutable { ascription: None, binding }
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::InlineConstant { subpattern: ref pattern, def, .. } => {
|
PatKind::InlineConstant { subpattern: ref pattern, def, .. } => {
|
||||||
// Apply a type ascription for the inline constant to the value at `match_pair.place`
|
// Apply a type ascription for the inline constant to the value at `match_pair.place`
|
||||||
let ascription = place.try_to_place(cx).map(|source| {
|
let ascription = place.map(|source| {
|
||||||
let span = pattern.span;
|
let span = pattern.span;
|
||||||
let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id());
|
let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id());
|
||||||
let args = ty::InlineConstArgs::new(
|
let args = ty::InlineConstArgs::new(
|
||||||
@ -203,16 +205,16 @@ pub(in crate::build) fn new(
|
|||||||
super::Ascription { annotation, source, variance: ty::Contravariant }
|
super::Ascription { annotation, source, variance: ty::Contravariant }
|
||||||
});
|
});
|
||||||
|
|
||||||
subpairs.push(MatchPair::new(place.clone(), pattern, cx));
|
subpairs.push(MatchPair::new(place_builder, pattern, cx));
|
||||||
TestCase::Irrefutable { ascription, binding: None }
|
TestCase::Irrefutable { ascription, binding: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Array { ref prefix, ref slice, ref suffix } => {
|
PatKind::Array { ref prefix, ref slice, ref suffix } => {
|
||||||
cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix);
|
cx.prefix_slice_suffix(&mut subpairs, &place_builder, prefix, slice, suffix);
|
||||||
default_irrefutable()
|
default_irrefutable()
|
||||||
}
|
}
|
||||||
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
|
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
|
||||||
cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix);
|
cx.prefix_slice_suffix(&mut subpairs, &place_builder, prefix, slice, suffix);
|
||||||
|
|
||||||
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
|
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
|
||||||
default_irrefutable()
|
default_irrefutable()
|
||||||
@ -225,7 +227,7 @@ pub(in crate::build) fn new(
|
|||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Variant { adt_def, variant_index, args, ref subpatterns } => {
|
PatKind::Variant { adt_def, variant_index, args, ref subpatterns } => {
|
||||||
let downcast_place = place.clone().downcast(adt_def, variant_index); // `(x as Variant)`
|
let downcast_place = place_builder.downcast(adt_def, variant_index); // `(x as Variant)`
|
||||||
subpairs = cx.field_match_pairs(downcast_place, subpatterns);
|
subpairs = cx.field_match_pairs(downcast_place, subpatterns);
|
||||||
|
|
||||||
let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
|
let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
|
||||||
@ -247,13 +249,12 @@ pub(in crate::build) fn new(
|
|||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Leaf { ref subpatterns } => {
|
PatKind::Leaf { ref subpatterns } => {
|
||||||
subpairs = cx.field_match_pairs(place.clone(), subpatterns);
|
subpairs = cx.field_match_pairs(place_builder, subpatterns);
|
||||||
default_irrefutable()
|
default_irrefutable()
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Deref { ref subpattern } => {
|
PatKind::Deref { ref subpattern } => {
|
||||||
let place_builder = place.clone().deref();
|
subpairs.push(MatchPair::new(place_builder.deref(), subpattern, cx));
|
||||||
subpairs.push(MatchPair::new(place_builder, subpattern, cx));
|
|
||||||
default_irrefutable()
|
default_irrefutable()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,8 +311,8 @@ fn visit_match_pair(&mut self, match_pair: &MatchPair<'_, 'tcx>) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Insert a Shallow borrow of any place that is switched on.
|
// Insert a Shallow borrow of any place that is switched on.
|
||||||
if let Some(resolved_place) = match_pair.place.try_to_place(self.cx) {
|
if let Some(place) = match_pair.place {
|
||||||
self.fake_borrows.insert(resolved_place);
|
self.fake_borrows.insert(place);
|
||||||
}
|
}
|
||||||
|
|
||||||
for subpair in &match_pair.subpairs {
|
for subpair in &match_pair.subpairs {
|
||||||
|
@ -170,6 +170,7 @@
|
|||||||
#![feature(unicode_internals)]
|
#![feature(unicode_internals)]
|
||||||
#![feature(unsize)]
|
#![feature(unsize)]
|
||||||
#![feature(utf8_chunks)]
|
#![feature(utf8_chunks)]
|
||||||
|
#![feature(vec_pop_if)]
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
//
|
//
|
||||||
// Language features:
|
// Language features:
|
||||||
|
@ -2058,6 +2058,31 @@ pub fn pop(&mut self) -> Option<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes and returns the last element in a vector if the predicate
|
||||||
|
/// returns `true`, or [`None`] if the predicate returns false or the vector
|
||||||
|
/// is empty.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(vec_pop_if)]
|
||||||
|
///
|
||||||
|
/// let mut vec = vec![1, 2, 3, 4];
|
||||||
|
/// let pred = |x: &mut i32| *x % 2 == 0;
|
||||||
|
///
|
||||||
|
/// assert_eq!(vec.pop_if(pred), Some(4));
|
||||||
|
/// assert_eq!(vec, [1, 2, 3]);
|
||||||
|
/// assert_eq!(vec.pop_if(pred), None);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "vec_pop_if", issue = "122741")]
|
||||||
|
pub fn pop_if<F>(&mut self, f: F) -> Option<T>
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut T) -> bool,
|
||||||
|
{
|
||||||
|
let last = self.last_mut()?;
|
||||||
|
if f(last) { self.pop() } else { None }
|
||||||
|
}
|
||||||
|
|
||||||
/// Moves all the elements of `other` into `self`, leaving `other` empty.
|
/// Moves all the elements of `other` into `self`, leaving `other` empty.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#![feature(strict_provenance)]
|
#![feature(strict_provenance)]
|
||||||
#![feature(drain_keep_rest)]
|
#![feature(drain_keep_rest)]
|
||||||
#![feature(local_waker)]
|
#![feature(local_waker)]
|
||||||
|
#![feature(vec_pop_if)]
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![deny(fuzzy_provenance_casts)]
|
#![deny(fuzzy_provenance_casts)]
|
||||||
#![deny(unsafe_op_in_unsafe_fn)]
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
|
@ -2644,6 +2644,36 @@ fn test_vec_from_array_mut_ref() {
|
|||||||
assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]);
|
assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pop_if() {
|
||||||
|
let mut v = vec![1, 2, 3, 4];
|
||||||
|
let pred = |x: &mut i32| *x % 2 == 0;
|
||||||
|
|
||||||
|
assert_eq!(v.pop_if(pred), Some(4));
|
||||||
|
assert_eq!(v, [1, 2, 3]);
|
||||||
|
|
||||||
|
assert_eq!(v.pop_if(pred), None);
|
||||||
|
assert_eq!(v, [1, 2, 3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pop_if_empty() {
|
||||||
|
let mut v = Vec::<i32>::new();
|
||||||
|
assert_eq!(v.pop_if(|_| true), None);
|
||||||
|
assert!(v.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pop_if_mutates() {
|
||||||
|
let mut v = vec![1];
|
||||||
|
let pred = |x: &mut i32| {
|
||||||
|
*x += 1;
|
||||||
|
false
|
||||||
|
};
|
||||||
|
assert_eq!(v.pop_if(pred), None);
|
||||||
|
assert_eq!(v, [2]);
|
||||||
|
}
|
||||||
|
|
||||||
/// This assortment of tests, in combination with miri, verifies we handle UB on fishy arguments
|
/// This assortment of tests, in combination with miri, verifies we handle UB on fishy arguments
|
||||||
/// in the stdlib. Draining and extending the allocation are fairly well-tested earlier, but
|
/// in the stdlib. Draining and extending the allocation are fairly well-tested earlier, but
|
||||||
/// `vec.insert(usize::MAX, val)` once slipped by!
|
/// `vec.insert(usize::MAX, val)` once slipped by!
|
||||||
|
@ -580,6 +580,10 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|||||||
io::Read::read(&mut &*self, buf)
|
io::Read::read(&mut &*self, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
|
||||||
|
io::Read::read_buf(&mut &*self, buf)
|
||||||
|
}
|
||||||
|
|
||||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
io::Read::read_vectored(&mut &*self, bufs)
|
io::Read::read_vectored(&mut &*self, bufs)
|
||||||
}
|
}
|
||||||
@ -596,6 +600,10 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|||||||
self.0.read(buf)
|
self.0.read(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
|
||||||
|
self.0.read_buf(buf)
|
||||||
|
}
|
||||||
|
|
||||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
self.0.read_vectored(bufs)
|
self.0.read_vectored(bufs)
|
||||||
}
|
}
|
||||||
|
@ -31,13 +31,14 @@
|
|||||||
/// <details><summary>Potential deadlock example</summary>
|
/// <details><summary>Potential deadlock example</summary>
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
/// // Thread 1 | // Thread 2
|
/// // Thread 1 | // Thread 2
|
||||||
/// let _rg = lock.read(); |
|
/// let _rg1 = lock.read(); |
|
||||||
/// | // will block
|
/// | // will block
|
||||||
/// | let _wg = lock.write();
|
/// | let _wg = lock.write();
|
||||||
/// // may deadlock |
|
/// // may deadlock |
|
||||||
/// let _rg = lock.read(); |
|
/// let _rg2 = lock.read(); |
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
/// </details>
|
/// </details>
|
||||||
///
|
///
|
||||||
/// The type parameter `T` represents the data that this lock protects. It is
|
/// The type parameter `T` represents the data that this lock protects. It is
|
||||||
|
@ -167,6 +167,8 @@ pub fn read_buf(&self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
target_os = "aix",
|
||||||
|
target_os = "dragonfly", // DragonFly 1.5
|
||||||
target_os = "emscripten",
|
target_os = "emscripten",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
target_os = "fuchsia",
|
target_os = "fuchsia",
|
||||||
@ -174,6 +176,7 @@ pub fn read_buf(&self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
|||||||
target_os = "illumos",
|
target_os = "illumos",
|
||||||
target_os = "linux",
|
target_os = "linux",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
|
target_os = "openbsd", // OpenBSD 2.7
|
||||||
))]
|
))]
|
||||||
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
|
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
|
||||||
let ret = cvt(unsafe {
|
let ret = cvt(unsafe {
|
||||||
@ -188,7 +191,9 @@ pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(
|
#[cfg(not(any(
|
||||||
|
target_os = "aix",
|
||||||
target_os = "android",
|
target_os = "android",
|
||||||
|
target_os = "dragonfly",
|
||||||
target_os = "emscripten",
|
target_os = "emscripten",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
target_os = "fuchsia",
|
target_os = "fuchsia",
|
||||||
@ -199,6 +204,8 @@ pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::
|
|||||||
target_os = "linux",
|
target_os = "linux",
|
||||||
target_os = "macos",
|
target_os = "macos",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
|
target_os = "openbsd",
|
||||||
|
target_os = "watchos",
|
||||||
)))]
|
)))]
|
||||||
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
|
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
|
||||||
io::default_read_vectored(|b| self.read_at(b, offset), bufs)
|
io::default_read_vectored(|b| self.read_at(b, offset), bufs)
|
||||||
@ -236,9 +243,10 @@ fn preadv(
|
|||||||
// no `syscall` possible in these platform.
|
// no `syscall` possible in these platform.
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
all(target_os = "android", target_pointer_width = "32"),
|
all(target_os = "android", target_pointer_width = "32"),
|
||||||
target_os = "ios",
|
target_os = "ios", // ios 14.0
|
||||||
target_os = "tvos",
|
target_os = "tvos", // tvos 14.0
|
||||||
target_os = "macos",
|
target_os = "macos", // macos 11.0
|
||||||
|
target_os = "watchos", // watchos 7.0
|
||||||
))]
|
))]
|
||||||
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
|
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
|
||||||
super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
|
super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
|
||||||
@ -318,6 +326,8 @@ pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
target_os = "aix",
|
||||||
|
target_os = "dragonfly", // DragonFly 1.5
|
||||||
target_os = "emscripten",
|
target_os = "emscripten",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
target_os = "fuchsia",
|
target_os = "fuchsia",
|
||||||
@ -325,6 +335,7 @@ pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
|
|||||||
target_os = "illumos",
|
target_os = "illumos",
|
||||||
target_os = "linux",
|
target_os = "linux",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
|
target_os = "openbsd", // OpenBSD 2.7
|
||||||
))]
|
))]
|
||||||
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
|
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
|
||||||
let ret = cvt(unsafe {
|
let ret = cvt(unsafe {
|
||||||
@ -339,7 +350,9 @@ pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(
|
#[cfg(not(any(
|
||||||
|
target_os = "aix",
|
||||||
target_os = "android",
|
target_os = "android",
|
||||||
|
target_os = "dragonfly",
|
||||||
target_os = "emscripten",
|
target_os = "emscripten",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
target_os = "fuchsia",
|
target_os = "fuchsia",
|
||||||
@ -350,6 +363,8 @@ pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result
|
|||||||
target_os = "linux",
|
target_os = "linux",
|
||||||
target_os = "macos",
|
target_os = "macos",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
|
target_os = "openbsd",
|
||||||
|
target_os = "watchos",
|
||||||
)))]
|
)))]
|
||||||
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
|
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
|
||||||
io::default_write_vectored(|b| self.write_at(b, offset), bufs)
|
io::default_write_vectored(|b| self.write_at(b, offset), bufs)
|
||||||
@ -387,9 +402,10 @@ fn pwritev(
|
|||||||
// no `syscall` possible in these platform.
|
// no `syscall` possible in these platform.
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
all(target_os = "android", target_pointer_width = "32"),
|
all(target_os = "android", target_pointer_width = "32"),
|
||||||
target_os = "ios",
|
target_os = "ios", // ios 14.0
|
||||||
target_os = "tvos",
|
target_os = "tvos", // tvos 14.0
|
||||||
target_os = "macos",
|
target_os = "macos", // macos 11.0
|
||||||
|
target_os = "watchos", // watchos 7.0
|
||||||
))]
|
))]
|
||||||
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
|
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
|
||||||
super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
|
super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
|
||||||
|
@ -424,7 +424,7 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
|||||||
if !set.is_null() {
|
if !set.is_null() {
|
||||||
let mut count: usize = 0;
|
let mut count: usize = 0;
|
||||||
if libc::pthread_getaffinity_np(libc::pthread_self(), libc::_cpuset_size(set), set) == 0 {
|
if libc::pthread_getaffinity_np(libc::pthread_self(), libc::_cpuset_size(set), set) == 0 {
|
||||||
for i in 0..u64::MAX {
|
for i in 0..libc::cpuid_t::MAX {
|
||||||
match libc::_cpuset_isset(i, set) {
|
match libc::_cpuset_isset(i, set) {
|
||||||
-1 => break,
|
-1 => break,
|
||||||
0 => continue,
|
0 => continue,
|
||||||
|
Loading…
Reference in New Issue
Block a user