Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 9 pull requests #72747

Merged
merged 35 commits into from
May 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
34b5118
Suggest using std::mem::drop function instead of explicit destructor …
stanislav-tkach May 20, 2020
a9199de
Merge spans for the suggestion
stanislav-tkach May 22, 2020
68bab3e
Add total_cmp to f32 and f64, plus tests
golddranks May 22, 2020
b6eec22
Fix typo in src/libcore/num/f32.rs
golddranks May 25, 2020
d6650e0
Fix typo in src/libcore/num/f32.rs
golddranks May 25, 2020
bd68de8
remove unneeded and unidiomatic must_use
golddranks May 25, 2020
6973fd7
Add bit twiddling
golddranks May 25, 2020
8bc31ff
Fix the same typos again orz
golddranks May 25, 2020
c3dc8c4
Rename upvar_list to closure_captures
May 25, 2020
66da735
Add tracing issue for total_cmp
golddranks May 26, 2020
ca722b9
Add test for #56445
JohnTitor May 25, 2020
125f0ab
Add test for #68532
JohnTitor May 25, 2020
4b87f97
Add test for #70121
JohnTitor May 25, 2020
6315d0c
Add test for #71042
JohnTitor May 26, 2020
6ddbef1
Simplify suggestion
stanislav-tkach May 26, 2020
822ad87
Add Peekable::next_if
jyn514 May 18, 2020
42a4f5a
Fix grammar in liballoc raw_vec
pickfire May 28, 2020
813ce7a
`SocketAddr(V4|V6)?`::Display now correctly pads its content
Lucretiel May 20, 2020
defbd84
Added fast-path, tests
Lucretiel May 20, 2020
06a97a0
Clarify comment message & MAX_LENGTH const
Lucretiel May 22, 2020
12c03db
Add missing empty line in E0619 explanation
GuillaumeGomez May 29, 2020
3f13d97
liveness: Log information about used variables
tmiasko May 20, 2020
b3342b4
liveness: Remove unused clean_exit_var
tmiasko May 21, 2020
7c63014
liveness: Remove unused fallthrough_ln
tmiasko May 21, 2020
74fcbfb
liveness: Include upvars in the analysis
tmiasko May 21, 2020
4dc5661
liveness: Warn about unused captured variables
tmiasko May 22, 2020
cbcc4c4
Rollup merge of #72310 - jyn514:peekable-next-if, r=dtolnay
Dylan-DPC May 29, 2020
9c1f203
Rollup merge of #72383 - DarkEld3r:issue-72322, r=matthewjasper
Dylan-DPC May 29, 2020
8bce240
Rollup merge of #72398 - Lucretiel:ip-socket-display, r=Mark-Simulacrum
Dylan-DPC May 29, 2020
9ef6227
Rollup merge of #72465 - tmiasko:liveness-upvars, r=nikomatsakis
Dylan-DPC May 29, 2020
c09f0eb
Rollup merge of #72568 - golddranks:add_total_cmp_to_floats, r=sfackler
Dylan-DPC May 29, 2020
89cb4d7
Rollup merge of #72572 - JohnTitor:add-tests, r=matthewjasper
Dylan-DPC May 29, 2020
ed80e8e
Rollup merge of #72591 - sexxi-goose:rename_upvar_list-to-closure_cap…
Dylan-DPC May 29, 2020
510793b
Rollup merge of #72701 - pickfire:patch-1, r=Mark-Simulacrum
Dylan-DPC May 29, 2020
180a92c
Rollup merge of #72731 - GuillaumeGomez:cleanup-e0619, r=Dylan-DPC
Dylan-DPC May 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/liballoc/raw_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ impl<T, A: AllocRef> RawVec<T, A> {
/// `used_capacity + needed_extra_capacity` elements. If it doesn't already,
/// will reallocate the minimum possible amount of memory necessary.
/// Generally this will be exactly the amount of memory necessary,
/// but in principle the allocator is free to give back more than
/// but in principle the allocator is free to give back more than what
/// we asked for.
///
/// If `used_capacity` exceeds `self.capacity()`, this may fail to actually allocate
Expand Down
63 changes: 63 additions & 0 deletions src/libcore/iter/adapters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1619,6 +1619,69 @@ impl<I: Iterator> Peekable<I> {
let iter = &mut self.iter;
self.peeked.get_or_insert_with(|| iter.next()).as_ref()
}

/// Consume the next value of this iterator if a condition is true.
///
/// If `func` returns `true` for the next value of this iterator, consume and return it.
/// Otherwise, return `None`.
///
/// # Examples
/// Consume a number if it's equal to 0.
/// ```
/// #![feature(peekable_next_if)]
/// let mut iter = (0..5).peekable();
/// // The first item of the iterator is 0; consume it.
/// assert_eq!(iter.next_if(|&x| x == 0), Some(0));
/// // The next item returned is now 1, so `consume` will return `false`.
/// assert_eq!(iter.next_if(|&x| x == 0), None);
/// // `next_if` saves the value of the next item if it was not equal to `expected`.
/// assert_eq!(iter.next(), Some(1));
/// ```
///
/// Consume any number less than 10.
/// ```
/// #![feature(peekable_next_if)]
/// let mut iter = (1..20).peekable();
/// // Consume all numbers less than 10
/// while iter.next_if(|&x| x < 10).is_some() {}
/// // The next value returned will be 10
/// assert_eq!(iter.next(), Some(10));
/// ```
#[unstable(feature = "peekable_next_if", issue = "72480")]
pub fn next_if(&mut self, func: impl FnOnce(&I::Item) -> bool) -> Option<I::Item> {
match self.next() {
Some(matched) if func(&matched) => Some(matched),
other => {
// Since we called `self.next()`, we consumed `self.peeked`.
assert!(self.peeked.is_none());
self.peeked = Some(other);
None
}
}
}

/// Consume the next item if it is equal to `expected`.
///
/// # Example
/// Consume a number if it's equal to 0.
/// ```
/// #![feature(peekable_next_if)]
/// let mut iter = (0..5).peekable();
/// // The first item of the iterator is 0; consume it.
/// assert_eq!(iter.next_if_eq(&0), Some(0));
/// // The next item returned is now 1, so `consume` will return `false`.
/// assert_eq!(iter.next_if_eq(&0), None);
/// // `next_if_eq` saves the value of the next item if it was not equal to `expected`.
/// assert_eq!(iter.next(), Some(1));
/// ```
#[unstable(feature = "peekable_next_if", issue = "72480")]
pub fn next_if_eq<R>(&mut self, expected: &R) -> Option<I::Item>
where
R: ?Sized,
I::Item: PartialEq<R>,
{
self.next_if(|next| next == expected)
}
}

/// An iterator that rejects elements while `predicate` returns `true`.
Expand Down
74 changes: 74 additions & 0 deletions src/libcore/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,4 +810,78 @@ impl f32 {
pub fn from_ne_bytes(bytes: [u8; 4]) -> Self {
Self::from_bits(u32::from_ne_bytes(bytes))
}

/// Returns an ordering between self and other values.
/// Unlike the standard partial comparison between floating point numbers,
/// this comparison always produces an ordering in accordance to
/// the totalOrder predicate as defined in IEEE 754 (2008 revision)
/// floating point standard. The values are ordered in following order:
/// - Negative quiet NaN
/// - Negative signaling NaN
/// - Negative infinity
/// - Negative numbers
/// - Negative subnormal numbers
/// - Negative zero
/// - Positive zero
/// - Positive subnormal numbers
/// - Positive numbers
/// - Positive infinity
/// - Positive signaling NaN
/// - Positive quiet NaN
///
/// # Example
/// ```
/// #![feature(total_cmp)]
/// struct GoodBoy {
/// name: String,
/// weight: f32,
/// }
///
/// let mut bois = vec![
/// GoodBoy { name: "Pucci".to_owned(), weight: 0.1 },
/// GoodBoy { name: "Woofer".to_owned(), weight: 99.0 },
/// GoodBoy { name: "Yapper".to_owned(), weight: 10.0 },
/// GoodBoy { name: "Chonk".to_owned(), weight: f32::INFINITY },
/// GoodBoy { name: "Abs. Unit".to_owned(), weight: f32::NAN },
/// GoodBoy { name: "Floaty".to_owned(), weight: -5.0 },
/// ];
///
/// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
/// # assert!(bois.into_iter().map(|b| b.weight)
/// # .zip([-5.0, 0.1, 10.0, 99.0, f32::INFINITY, f32::NAN].iter())
/// # .all(|(a, b)| a.to_bits() == b.to_bits()))
/// ```
#[unstable(feature = "total_cmp", issue = "72599")]
#[inline]
pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
let mut left = self.to_bits() as i32;
let mut right = other.to_bits() as i32;

// In case of negatives, flip all the bits except the sign
// to achieve a similar layout as two's complement integers
//
// Why does this work? IEEE 754 floats consist of three fields:
// Sign bit, exponent and mantissa. The set of exponent and mantissa
// fields as a whole have the property that their bitwise order is
// equal to the numeric magnitude where the magnitude is defined.
// The magnitude is not normally defined on NaN values, but
// IEEE 754 totalOrder defines the NaN values also to follow the
// bitwise order. This leads to order explained in the doc comment.
// However, the representation of magnitude is the same for negative
// and positive numbers – only the sign bit is different.
// To easily compare the floats as signed integers, we need to
// flip the exponent and mantissa bits in case of negative numbers.
// We effectively convert the numbers to "two's complement" form.
//
// To do the flipping, we construct a mask and XOR against it.
// We branchlessly calculate an "all-ones except for the sign bit"
// mask from negative-signed values: right shifting sign-extends
// the integer, so we "fill" the mask with sign bits, and then
// convert to unsigned to push one more zero bit.
// On positive values, the mask is all zeros, so it's a no-op.
left ^= (((left >> 31) as u32) >> 1) as i32;
right ^= (((right >> 31) as u32) >> 1) as i32;

left.cmp(&right)
}
}
74 changes: 74 additions & 0 deletions src/libcore/num/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,4 +824,78 @@ impl f64 {
pub fn from_ne_bytes(bytes: [u8; 8]) -> Self {
Self::from_bits(u64::from_ne_bytes(bytes))
}

/// Returns an ordering between self and other values.
/// Unlike the standard partial comparison between floating point numbers,
/// this comparison always produces an ordering in accordance to
/// the totalOrder predicate as defined in IEEE 754 (2008 revision)
/// floating point standard. The values are ordered in following order:
/// - Negative quiet NaN
/// - Negative signaling NaN
/// - Negative infinity
/// - Negative numbers
/// - Negative subnormal numbers
/// - Negative zero
/// - Positive zero
/// - Positive subnormal numbers
/// - Positive numbers
/// - Positive infinity
/// - Positive signaling NaN
/// - Positive quiet NaN
///
/// # Example
/// ```
/// #![feature(total_cmp)]
/// struct GoodBoy {
/// name: String,
/// weight: f64,
/// }
///
/// let mut bois = vec![
/// GoodBoy { name: "Pucci".to_owned(), weight: 0.1 },
/// GoodBoy { name: "Woofer".to_owned(), weight: 99.0 },
/// GoodBoy { name: "Yapper".to_owned(), weight: 10.0 },
/// GoodBoy { name: "Chonk".to_owned(), weight: f64::INFINITY },
/// GoodBoy { name: "Abs. Unit".to_owned(), weight: f64::NAN },
/// GoodBoy { name: "Floaty".to_owned(), weight: -5.0 },
/// ];
///
/// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
/// # assert!(bois.into_iter().map(|b| b.weight)
/// # .zip([-5.0, 0.1, 10.0, 99.0, f64::INFINITY, f64::NAN].iter())
/// # .all(|(a, b)| a.to_bits() == b.to_bits()))
/// ```
#[unstable(feature = "total_cmp", issue = "72599")]
#[inline]
pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
let mut left = self.to_bits() as i64;
let mut right = other.to_bits() as i64;

// In case of negatives, flip all the bits except the sign
// to achieve a similar layout as two's complement integers
//
// Why does this work? IEEE 754 floats consist of three fields:
// Sign bit, exponent and mantissa. The set of exponent and mantissa
// fields as a whole have the property that their bitwise order is
// equal to the numeric magnitude where the magnitude is defined.
// The magnitude is not normally defined on NaN values, but
// IEEE 754 totalOrder defines the NaN values also to follow the
// bitwise order. This leads to order explained in the doc comment.
// However, the representation of magnitude is the same for negative
// and positive numbers – only the sign bit is different.
// To easily compare the floats as signed integers, we need to
// flip the exponent and mantissa bits in case of negative numbers.
// We effectively convert the numbers to "two's complement" form.
//
// To do the flipping, we construct a mask and XOR against it.
// We branchlessly calculate an "all-ones except for the sign bit"
// mask from negative-signed values: right shifting sign-extends
// the integer, so we "fill" the mask with sign bits, and then
// convert to unsigned to push one more zero bit.
// On positive values, the mask is all zeros, so it's a no-op.
left ^= (((left >> 63) as u64) >> 1) as i64;
right ^= (((right >> 63) as u64) >> 1) as i64;

left.cmp(&right)
}
}
24 changes: 24 additions & 0 deletions src/libcore/tests/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,30 @@ fn test_iterator_peekable_rfold() {
assert_eq!(i, xs.len());
}

#[test]
fn test_iterator_peekable_next_if_eq() {
// first, try on references
let xs = vec!["Heart", "of", "Gold"];
let mut it = xs.into_iter().peekable();
// try before `peek()`
assert_eq!(it.next_if_eq(&"trillian"), None);
assert_eq!(it.next_if_eq(&"Heart"), Some("Heart"));
// try after peek()
assert_eq!(it.peek(), Some(&"of"));
assert_eq!(it.next_if_eq(&"of"), Some("of"));
assert_eq!(it.next_if_eq(&"zaphod"), None);
// make sure `next()` still behaves
assert_eq!(it.next(), Some("Gold"));

// make sure comparison works for owned values
let xs = vec![String::from("Ludicrous"), "speed".into()];
let mut it = xs.into_iter().peekable();
// make sure basic functionality works
assert_eq!(it.next_if_eq("Ludicrous"), Some("Ludicrous".into()));
assert_eq!(it.next_if_eq("speed"), Some("speed".into()));
assert_eq!(it.next_if_eq(""), None);
}

/// This is an iterator that follows the Iterator contract,
/// but it is not fused. After having returned None once, it will start
/// producing elements if .next() is called again.
Expand Down
1 change: 1 addition & 0 deletions src/libcore/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#![feature(leading_trailing_ones)]
#![feature(const_forget)]
#![feature(option_unwrap_none)]
#![feature(peekable_next_if)]

extern crate test;

Expand Down
1 change: 1 addition & 0 deletions src/librustc_error_codes/error_codes/E0619.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#### Note: this error code is no longer emitted by the compiler.

The type-checker needed to know the type of an expression, but that type had not
yet been inferred.

Expand Down
8 changes: 4 additions & 4 deletions src/librustc_middle/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ pub struct TypeckTables<'tcx> {
/// The upvarID contains the HIR node ID and it also contains the full path
/// leading to the member of the struct or tuple that is used instead of the
/// entire variable.
pub upvar_list: ty::UpvarListMap,
pub closure_captures: ty::UpvarListMap,

/// Stores the type, expression, span and optional scope span of all types
/// that are live across the yield of this generator (if a generator).
Expand Down Expand Up @@ -447,7 +447,7 @@ impl<'tcx> TypeckTables<'tcx> {
used_trait_imports: Lrc::new(Default::default()),
tainted_by_errors: None,
concrete_opaque_types: Default::default(),
upvar_list: Default::default(),
closure_captures: Default::default(),
generator_interior_types: Default::default(),
}
}
Expand Down Expand Up @@ -688,7 +688,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
ref used_trait_imports,
tainted_by_errors,
ref concrete_opaque_types,
ref upvar_list,
ref closure_captures,
ref generator_interior_types,
} = *self;

Expand Down Expand Up @@ -721,7 +721,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
used_trait_imports.hash_stable(hcx, hasher);
tainted_by_errors.hash_stable(hcx, hasher);
concrete_opaque_types.hash_stable(hcx, hasher);
upvar_list.hash_stable(hcx, hasher);
closure_captures.hash_stable(hcx, hasher);
generator_interior_types.hash_stable(hcx, hasher);
})
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ fn do_mir_borrowck<'a, 'tcx>(
infcx.set_tainted_by_errors();
}
let upvars: Vec<_> = tables
.upvar_list
.closure_captures
.get(&def_id.to_def_id())
.into_iter()
.flat_map(|v| v.values())
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
let mut name = None;
if let Some(def_id) = def_id.as_local() {
let tables = self.ecx.tcx.typeck_tables_of(def_id);
if let Some(upvars) = tables.upvar_list.get(&def_id.to_def_id()) {
if let Some(upvars) = tables.closure_captures.get(&def_id.to_def_id()) {
// Sometimes the index is beyond the number of upvars (seen
// for a generator).
if let Some((&var_hir_id, _)) = upvars.get_index(field) {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir_build/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,11 +790,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let hir_tables = self.hir.tables();

// In analyze_closure() in upvar.rs we gathered a list of upvars used by a
// closure and we stored in a map called upvar_list in TypeckTables indexed
// indexed closure and we stored in a map called closure_captures in TypeckTables
// with the closure's DefId. Here, we run through that vec of UpvarIds for
// the given closure and use the necessary information to create upvar
// debuginfo and to fill `self.upvar_mutbls`.
if let Some(upvars) = hir_tables.upvar_list.get(&fn_def_id) {
if let Some(upvars) = hir_tables.closure_captures.get(&fn_def_id) {
let closure_env_arg = Local::new(1);
let mut closure_env_projs = vec![];
let mut closure_ty = self.local_decls[closure_env_arg].ty;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir_build/hair/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,7 @@ fn convert_var<'tcx>(
) -> ExprKind<'tcx> {
let upvar_index = cx
.tables()
.upvar_list
.closure_captures
.get(&cx.body_owner)
.and_then(|upvars| upvars.get_full(&var_hir_id).map(|(i, _, _)| i));

Expand Down
Loading