Skip to content

Commit 4bd32c9

Browse files
committed
Auto merge of #72747 - Dylan-DPC:rollup-vvydkgl, r=Dylan-DPC
Rollup of 9 pull requests Successful merges: - #72310 (Add Peekable::next_if) - #72383 (Suggest using std::mem::drop function instead of explicit destructor call) - #72398 (SocketAddr and friends now correctly pad its content) - #72465 (Warn about unused captured variables) - #72568 (Implement total_cmp for f32, f64) - #72572 (Add some regression tests) - #72591 (librustc_middle: Rename upvar_list to closure_captures) - #72701 (Fix grammar in liballoc raw_vec) - #72731 (Add missing empty line in E0619 explanation) Failed merges: r? @ghost
2 parents 96dd469 + 180a92c commit 4bd32c9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1274
-154
lines changed

src/liballoc/raw_vec.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ impl<T, A: AllocRef> RawVec<T, A> {
315315
/// `used_capacity + needed_extra_capacity` elements. If it doesn't already,
316316
/// will reallocate the minimum possible amount of memory necessary.
317317
/// Generally this will be exactly the amount of memory necessary,
318-
/// but in principle the allocator is free to give back more than
318+
/// but in principle the allocator is free to give back more than what
319319
/// we asked for.
320320
///
321321
/// If `used_capacity` exceeds `self.capacity()`, this may fail to actually allocate

src/libcore/iter/adapters/mod.rs

+63
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,69 @@ impl<I: Iterator> Peekable<I> {
16191619
let iter = &mut self.iter;
16201620
self.peeked.get_or_insert_with(|| iter.next()).as_ref()
16211621
}
1622+
1623+
/// Consume the next value of this iterator if a condition is true.
1624+
///
1625+
/// If `func` returns `true` for the next value of this iterator, consume and return it.
1626+
/// Otherwise, return `None`.
1627+
///
1628+
/// # Examples
1629+
/// Consume a number if it's equal to 0.
1630+
/// ```
1631+
/// #![feature(peekable_next_if)]
1632+
/// let mut iter = (0..5).peekable();
1633+
/// // The first item of the iterator is 0; consume it.
1634+
/// assert_eq!(iter.next_if(|&x| x == 0), Some(0));
1635+
/// // The next item returned is now 1, so `consume` will return `false`.
1636+
/// assert_eq!(iter.next_if(|&x| x == 0), None);
1637+
/// // `next_if` saves the value of the next item if it was not equal to `expected`.
1638+
/// assert_eq!(iter.next(), Some(1));
1639+
/// ```
1640+
///
1641+
/// Consume any number less than 10.
1642+
/// ```
1643+
/// #![feature(peekable_next_if)]
1644+
/// let mut iter = (1..20).peekable();
1645+
/// // Consume all numbers less than 10
1646+
/// while iter.next_if(|&x| x < 10).is_some() {}
1647+
/// // The next value returned will be 10
1648+
/// assert_eq!(iter.next(), Some(10));
1649+
/// ```
1650+
#[unstable(feature = "peekable_next_if", issue = "72480")]
1651+
pub fn next_if(&mut self, func: impl FnOnce(&I::Item) -> bool) -> Option<I::Item> {
1652+
match self.next() {
1653+
Some(matched) if func(&matched) => Some(matched),
1654+
other => {
1655+
// Since we called `self.next()`, we consumed `self.peeked`.
1656+
assert!(self.peeked.is_none());
1657+
self.peeked = Some(other);
1658+
None
1659+
}
1660+
}
1661+
}
1662+
1663+
/// Consume the next item if it is equal to `expected`.
1664+
///
1665+
/// # Example
1666+
/// Consume a number if it's equal to 0.
1667+
/// ```
1668+
/// #![feature(peekable_next_if)]
1669+
/// let mut iter = (0..5).peekable();
1670+
/// // The first item of the iterator is 0; consume it.
1671+
/// assert_eq!(iter.next_if_eq(&0), Some(0));
1672+
/// // The next item returned is now 1, so `consume` will return `false`.
1673+
/// assert_eq!(iter.next_if_eq(&0), None);
1674+
/// // `next_if_eq` saves the value of the next item if it was not equal to `expected`.
1675+
/// assert_eq!(iter.next(), Some(1));
1676+
/// ```
1677+
#[unstable(feature = "peekable_next_if", issue = "72480")]
1678+
pub fn next_if_eq<R>(&mut self, expected: &R) -> Option<I::Item>
1679+
where
1680+
R: ?Sized,
1681+
I::Item: PartialEq<R>,
1682+
{
1683+
self.next_if(|next| next == expected)
1684+
}
16221685
}
16231686

16241687
/// An iterator that rejects elements while `predicate` returns `true`.

src/libcore/num/f32.rs

+74
Original file line numberDiff line numberDiff line change
@@ -810,4 +810,78 @@ impl f32 {
810810
pub fn from_ne_bytes(bytes: [u8; 4]) -> Self {
811811
Self::from_bits(u32::from_ne_bytes(bytes))
812812
}
813+
814+
/// Returns an ordering between self and other values.
815+
/// Unlike the standard partial comparison between floating point numbers,
816+
/// this comparison always produces an ordering in accordance to
817+
/// the totalOrder predicate as defined in IEEE 754 (2008 revision)
818+
/// floating point standard. The values are ordered in following order:
819+
/// - Negative quiet NaN
820+
/// - Negative signaling NaN
821+
/// - Negative infinity
822+
/// - Negative numbers
823+
/// - Negative subnormal numbers
824+
/// - Negative zero
825+
/// - Positive zero
826+
/// - Positive subnormal numbers
827+
/// - Positive numbers
828+
/// - Positive infinity
829+
/// - Positive signaling NaN
830+
/// - Positive quiet NaN
831+
///
832+
/// # Example
833+
/// ```
834+
/// #![feature(total_cmp)]
835+
/// struct GoodBoy {
836+
/// name: String,
837+
/// weight: f32,
838+
/// }
839+
///
840+
/// let mut bois = vec![
841+
/// GoodBoy { name: "Pucci".to_owned(), weight: 0.1 },
842+
/// GoodBoy { name: "Woofer".to_owned(), weight: 99.0 },
843+
/// GoodBoy { name: "Yapper".to_owned(), weight: 10.0 },
844+
/// GoodBoy { name: "Chonk".to_owned(), weight: f32::INFINITY },
845+
/// GoodBoy { name: "Abs. Unit".to_owned(), weight: f32::NAN },
846+
/// GoodBoy { name: "Floaty".to_owned(), weight: -5.0 },
847+
/// ];
848+
///
849+
/// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
850+
/// # assert!(bois.into_iter().map(|b| b.weight)
851+
/// # .zip([-5.0, 0.1, 10.0, 99.0, f32::INFINITY, f32::NAN].iter())
852+
/// # .all(|(a, b)| a.to_bits() == b.to_bits()))
853+
/// ```
854+
#[unstable(feature = "total_cmp", issue = "72599")]
855+
#[inline]
856+
pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
857+
let mut left = self.to_bits() as i32;
858+
let mut right = other.to_bits() as i32;
859+
860+
// In case of negatives, flip all the bits except the sign
861+
// to achieve a similar layout as two's complement integers
862+
//
863+
// Why does this work? IEEE 754 floats consist of three fields:
864+
// Sign bit, exponent and mantissa. The set of exponent and mantissa
865+
// fields as a whole have the property that their bitwise order is
866+
// equal to the numeric magnitude where the magnitude is defined.
867+
// The magnitude is not normally defined on NaN values, but
868+
// IEEE 754 totalOrder defines the NaN values also to follow the
869+
// bitwise order. This leads to order explained in the doc comment.
870+
// However, the representation of magnitude is the same for negative
871+
// and positive numbers – only the sign bit is different.
872+
// To easily compare the floats as signed integers, we need to
873+
// flip the exponent and mantissa bits in case of negative numbers.
874+
// We effectively convert the numbers to "two's complement" form.
875+
//
876+
// To do the flipping, we construct a mask and XOR against it.
877+
// We branchlessly calculate an "all-ones except for the sign bit"
878+
// mask from negative-signed values: right shifting sign-extends
879+
// the integer, so we "fill" the mask with sign bits, and then
880+
// convert to unsigned to push one more zero bit.
881+
// On positive values, the mask is all zeros, so it's a no-op.
882+
left ^= (((left >> 31) as u32) >> 1) as i32;
883+
right ^= (((right >> 31) as u32) >> 1) as i32;
884+
885+
left.cmp(&right)
886+
}
813887
}

src/libcore/num/f64.rs

+74
Original file line numberDiff line numberDiff line change
@@ -824,4 +824,78 @@ impl f64 {
824824
pub fn from_ne_bytes(bytes: [u8; 8]) -> Self {
825825
Self::from_bits(u64::from_ne_bytes(bytes))
826826
}
827+
828+
/// Returns an ordering between self and other values.
829+
/// Unlike the standard partial comparison between floating point numbers,
830+
/// this comparison always produces an ordering in accordance to
831+
/// the totalOrder predicate as defined in IEEE 754 (2008 revision)
832+
/// floating point standard. The values are ordered in following order:
833+
/// - Negative quiet NaN
834+
/// - Negative signaling NaN
835+
/// - Negative infinity
836+
/// - Negative numbers
837+
/// - Negative subnormal numbers
838+
/// - Negative zero
839+
/// - Positive zero
840+
/// - Positive subnormal numbers
841+
/// - Positive numbers
842+
/// - Positive infinity
843+
/// - Positive signaling NaN
844+
/// - Positive quiet NaN
845+
///
846+
/// # Example
847+
/// ```
848+
/// #![feature(total_cmp)]
849+
/// struct GoodBoy {
850+
/// name: String,
851+
/// weight: f64,
852+
/// }
853+
///
854+
/// let mut bois = vec![
855+
/// GoodBoy { name: "Pucci".to_owned(), weight: 0.1 },
856+
/// GoodBoy { name: "Woofer".to_owned(), weight: 99.0 },
857+
/// GoodBoy { name: "Yapper".to_owned(), weight: 10.0 },
858+
/// GoodBoy { name: "Chonk".to_owned(), weight: f64::INFINITY },
859+
/// GoodBoy { name: "Abs. Unit".to_owned(), weight: f64::NAN },
860+
/// GoodBoy { name: "Floaty".to_owned(), weight: -5.0 },
861+
/// ];
862+
///
863+
/// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
864+
/// # assert!(bois.into_iter().map(|b| b.weight)
865+
/// # .zip([-5.0, 0.1, 10.0, 99.0, f64::INFINITY, f64::NAN].iter())
866+
/// # .all(|(a, b)| a.to_bits() == b.to_bits()))
867+
/// ```
868+
#[unstable(feature = "total_cmp", issue = "72599")]
869+
#[inline]
870+
pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
871+
let mut left = self.to_bits() as i64;
872+
let mut right = other.to_bits() as i64;
873+
874+
// In case of negatives, flip all the bits except the sign
875+
// to achieve a similar layout as two's complement integers
876+
//
877+
// Why does this work? IEEE 754 floats consist of three fields:
878+
// Sign bit, exponent and mantissa. The set of exponent and mantissa
879+
// fields as a whole have the property that their bitwise order is
880+
// equal to the numeric magnitude where the magnitude is defined.
881+
// The magnitude is not normally defined on NaN values, but
882+
// IEEE 754 totalOrder defines the NaN values also to follow the
883+
// bitwise order. This leads to order explained in the doc comment.
884+
// However, the representation of magnitude is the same for negative
885+
// and positive numbers – only the sign bit is different.
886+
// To easily compare the floats as signed integers, we need to
887+
// flip the exponent and mantissa bits in case of negative numbers.
888+
// We effectively convert the numbers to "two's complement" form.
889+
//
890+
// To do the flipping, we construct a mask and XOR against it.
891+
// We branchlessly calculate an "all-ones except for the sign bit"
892+
// mask from negative-signed values: right shifting sign-extends
893+
// the integer, so we "fill" the mask with sign bits, and then
894+
// convert to unsigned to push one more zero bit.
895+
// On positive values, the mask is all zeros, so it's a no-op.
896+
left ^= (((left >> 63) as u64) >> 1) as i64;
897+
right ^= (((right >> 63) as u64) >> 1) as i64;
898+
899+
left.cmp(&right)
900+
}
827901
}

src/libcore/tests/iter.rs

+24
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,30 @@ fn test_iterator_peekable_rfold() {
813813
assert_eq!(i, xs.len());
814814
}
815815

816+
#[test]
817+
fn test_iterator_peekable_next_if_eq() {
818+
// first, try on references
819+
let xs = vec!["Heart", "of", "Gold"];
820+
let mut it = xs.into_iter().peekable();
821+
// try before `peek()`
822+
assert_eq!(it.next_if_eq(&"trillian"), None);
823+
assert_eq!(it.next_if_eq(&"Heart"), Some("Heart"));
824+
// try after peek()
825+
assert_eq!(it.peek(), Some(&"of"));
826+
assert_eq!(it.next_if_eq(&"of"), Some("of"));
827+
assert_eq!(it.next_if_eq(&"zaphod"), None);
828+
// make sure `next()` still behaves
829+
assert_eq!(it.next(), Some("Gold"));
830+
831+
// make sure comparison works for owned values
832+
let xs = vec![String::from("Ludicrous"), "speed".into()];
833+
let mut it = xs.into_iter().peekable();
834+
// make sure basic functionality works
835+
assert_eq!(it.next_if_eq("Ludicrous"), Some("Ludicrous".into()));
836+
assert_eq!(it.next_if_eq("speed"), Some("speed".into()));
837+
assert_eq!(it.next_if_eq(""), None);
838+
}
839+
816840
/// This is an iterator that follows the Iterator contract,
817841
/// but it is not fused. After having returned None once, it will start
818842
/// producing elements if .next() is called again.

src/libcore/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#![feature(leading_trailing_ones)]
4444
#![feature(const_forget)]
4545
#![feature(option_unwrap_none)]
46+
#![feature(peekable_next_if)]
4647

4748
extern crate test;
4849

src/librustc_error_codes/error_codes/E0619.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#### Note: this error code is no longer emitted by the compiler.
2+
23
The type-checker needed to know the type of an expression, but that type had not
34
yet been inferred.
45

src/librustc_middle/ty/context.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ pub struct TypeckTables<'tcx> {
419419
/// The upvarID contains the HIR node ID and it also contains the full path
420420
/// leading to the member of the struct or tuple that is used instead of the
421421
/// entire variable.
422-
pub upvar_list: ty::UpvarListMap,
422+
pub closure_captures: ty::UpvarListMap,
423423

424424
/// Stores the type, expression, span and optional scope span of all types
425425
/// that are live across the yield of this generator (if a generator).
@@ -447,7 +447,7 @@ impl<'tcx> TypeckTables<'tcx> {
447447
used_trait_imports: Lrc::new(Default::default()),
448448
tainted_by_errors: None,
449449
concrete_opaque_types: Default::default(),
450-
upvar_list: Default::default(),
450+
closure_captures: Default::default(),
451451
generator_interior_types: Default::default(),
452452
}
453453
}
@@ -688,7 +688,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
688688
ref used_trait_imports,
689689
tainted_by_errors,
690690
ref concrete_opaque_types,
691-
ref upvar_list,
691+
ref closure_captures,
692692
ref generator_interior_types,
693693
} = *self;
694694

@@ -721,7 +721,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
721721
used_trait_imports.hash_stable(hcx, hasher);
722722
tainted_by_errors.hash_stable(hcx, hasher);
723723
concrete_opaque_types.hash_stable(hcx, hasher);
724-
upvar_list.hash_stable(hcx, hasher);
724+
closure_captures.hash_stable(hcx, hasher);
725725
generator_interior_types.hash_stable(hcx, hasher);
726726
})
727727
}

src/librustc_mir/borrow_check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ fn do_mir_borrowck<'a, 'tcx>(
142142
infcx.set_tainted_by_errors();
143143
}
144144
let upvars: Vec<_> = tables
145-
.upvar_list
145+
.closure_captures
146146
.get(&def_id.to_def_id())
147147
.into_iter()
148148
.flat_map(|v| v.values())

src/librustc_mir/interpret/validity.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
227227
let mut name = None;
228228
if let Some(def_id) = def_id.as_local() {
229229
let tables = self.ecx.tcx.typeck_tables_of(def_id);
230-
if let Some(upvars) = tables.upvar_list.get(&def_id.to_def_id()) {
230+
if let Some(upvars) = tables.closure_captures.get(&def_id.to_def_id()) {
231231
// Sometimes the index is beyond the number of upvars (seen
232232
// for a generator).
233233
if let Some((&var_hir_id, _)) = upvars.get_index(field) {

src/librustc_mir_build/build/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -790,11 +790,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
790790
let hir_tables = self.hir.tables();
791791

792792
// In analyze_closure() in upvar.rs we gathered a list of upvars used by a
793-
// closure and we stored in a map called upvar_list in TypeckTables indexed
793+
// indexed closure and we stored in a map called closure_captures in TypeckTables
794794
// with the closure's DefId. Here, we run through that vec of UpvarIds for
795795
// the given closure and use the necessary information to create upvar
796796
// debuginfo and to fill `self.upvar_mutbls`.
797-
if let Some(upvars) = hir_tables.upvar_list.get(&fn_def_id) {
797+
if let Some(upvars) = hir_tables.closure_captures.get(&fn_def_id) {
798798
let closure_env_arg = Local::new(1);
799799
let mut closure_env_projs = vec![];
800800
let mut closure_ty = self.local_decls[closure_env_arg].ty;

src/librustc_mir_build/hair/cx/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ fn convert_var<'tcx>(
884884
) -> ExprKind<'tcx> {
885885
let upvar_index = cx
886886
.tables()
887-
.upvar_list
887+
.closure_captures
888888
.get(&cx.body_owner)
889889
.and_then(|upvars| upvars.get_full(&var_hir_id).map(|(i, _, _)| i));
890890

0 commit comments

Comments
 (0)