Skip to content

Commit

Permalink
Auto merge of #69309 - Dylan-DPC:rollup-gjdqx7l, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #68705 (Add LinkedList::remove())
 - #68945 (Stabilize Once::is_completed)
 - #68978 (Make integer exponentiation methods unstably const)
 - #69266 (Fix race condition when allocating source files in SourceMap)
 - #69287 (Clean up E0317 explanation)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Feb 20, 2020
2 parents 6af388b + 941ce1a commit 93711d0
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 55 deletions.
46 changes: 46 additions & 0 deletions src/liballoc/collections/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,52 @@ impl<T> LinkedList<T> {
unsafe { self.split_off_after_node(split_node, at) }
}

/// Removes the element at the given index and returns it.
///
/// This operation should compute in O(n) time.
///
/// # Panics
/// Panics if at >= len
///
/// # Examples
///
/// ```
/// #![feature(linked_list_remove)]
/// use std::collections::LinkedList;
///
/// let mut d = LinkedList::new();
///
/// d.push_front(1);
/// d.push_front(2);
/// d.push_front(3);
///
/// assert_eq!(d.remove(1), 2);
/// assert_eq!(d.remove(0), 3);
/// assert_eq!(d.remove(0), 1);
/// ```
#[unstable(feature = "linked_list_remove", issue = "69210")]
pub fn remove(&mut self, at: usize) -> T {
let len = self.len();
assert!(at < len, "Cannot remove at an index outside of the list bounds");

// Below, we iterate towards the node at the given index, either from
// the start or the end, depending on which would be faster.
let offset_from_end = len - at - 1;
if at <= offset_from_end {
let mut cursor = self.cursor_front_mut();
for _ in 0..at {
cursor.move_next();
}
cursor.remove_current().unwrap()
} else {
let mut cursor = self.cursor_back_mut();
for _ in 0..offset_from_end {
cursor.move_prev();
}
cursor.remove_current().unwrap()
}
}

/// Creates an iterator which uses a closure to determine if an element should be removed.
///
/// If the closure returns true, then the element is removed and yielded.
Expand Down
3 changes: 3 additions & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,14 @@
#![feature(const_ascii_ctype_on_intrinsics)]
#![feature(const_alloc_layout)]
#![feature(const_if_match)]
#![feature(const_loop)]
#![feature(const_checked_int_methods)]
#![feature(const_euclidean_int_methods)]
#![feature(const_overflowing_int_methods)]
#![feature(const_saturating_int_methods)]
#![feature(const_int_unchecked_arith)]
#![feature(const_int_pow)]
#![feature(constctlz)]
#![feature(const_panic)]
#![feature(const_fn_union)]
#![feature(const_generics)]
Expand Down
69 changes: 46 additions & 23 deletions src/libcore/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,18 @@ use crate::convert::Infallible;
use crate::fmt;
use crate::intrinsics;
use crate::mem;
use crate::ops;
use crate::str::FromStr;

// Used because the `?` operator is not allowed in a const context.
macro_rules! try_opt {
($e:expr) => {
match $e {
Some(x) => x,
None => return None,
}
};
}

macro_rules! impl_nonzero_fmt {
( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
$(
Expand Down Expand Up @@ -993,26 +1002,27 @@ $EndFeature, "
```"),

#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
let mut base = self;
let mut acc: Self = 1;

while exp > 1 {
if (exp & 1) == 1 {
acc = acc.checked_mul(base)?;
acc = try_opt!(acc.checked_mul(base));
}
exp /= 2;
base = base.checked_mul(base)?;
base = try_opt!(base.checked_mul(base));
}

// Deal with the final bit of the exponent separately, since
// squaring the base afterwards is not necessary and may cause a
// needless overflow.
if exp == 1 {
acc = acc.checked_mul(base)?;
acc = try_opt!(acc.checked_mul(base));
}

Some(acc)
Expand Down Expand Up @@ -1180,10 +1190,11 @@ assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT
$EndFeature, "
```"),
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub fn saturating_pow(self, exp: u32) -> Self {
pub const fn saturating_pow(self, exp: u32) -> Self {
match self.checked_pow(exp) {
Some(x) => x,
None if self < 0 && exp % 2 == 1 => Self::min_value(),
Expand Down Expand Up @@ -1523,10 +1534,11 @@ assert_eq!(3i8.wrapping_pow(6), -39);",
$EndFeature, "
```"),
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub fn wrapping_pow(self, mut exp: u32) -> Self {
pub const fn wrapping_pow(self, mut exp: u32) -> Self {
let mut base = self;
let mut acc: Self = 1;

Expand Down Expand Up @@ -1900,10 +1912,11 @@ assert_eq!(3i8.overflowing_pow(5), (-13, true));",
$EndFeature, "
```"),
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
let mut base = self;
let mut acc: Self = 1;
let mut overflown = false;
Expand Down Expand Up @@ -1949,11 +1962,12 @@ assert_eq!(x.pow(5), 32);",
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[rustc_inherit_overflow_checks]
pub fn pow(self, mut exp: u32) -> Self {
pub const fn pow(self, mut exp: u32) -> Self {
let mut base = self;
let mut acc = 1;

Expand Down Expand Up @@ -3119,26 +3133,27 @@ Basic usage:
assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", $EndFeature, "
```"),
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
let mut base = self;
let mut acc: Self = 1;

while exp > 1 {
if (exp & 1) == 1 {
acc = acc.checked_mul(base)?;
acc = try_opt!(acc.checked_mul(base));
}
exp /= 2;
base = base.checked_mul(base)?;
base = try_opt!(base.checked_mul(base));
}

// Deal with the final bit of the exponent separately, since
// squaring the base afterwards is not necessary and may cause a
// needless overflow.
if exp == 1 {
acc = acc.checked_mul(base)?;
acc = try_opt!(acc.checked_mul(base));
}

Some(acc)
Expand Down Expand Up @@ -3234,10 +3249,11 @@ assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT
$EndFeature, "
```"),
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub fn saturating_pow(self, exp: u32) -> Self {
pub const fn saturating_pow(self, exp: u32) -> Self {
match self.checked_pow(exp) {
Some(x) => x,
None => Self::max_value(),
Expand Down Expand Up @@ -3527,10 +3543,11 @@ Basic usage:
assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, "
```"),
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub fn wrapping_pow(self, mut exp: u32) -> Self {
pub const fn wrapping_pow(self, mut exp: u32) -> Self {
let mut base = self;
let mut acc: Self = 1;

Expand Down Expand Up @@ -3853,10 +3870,11 @@ Basic usage:
assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, "
```"),
#[stable(feature = "no_panic_pow", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
let mut base = self;
let mut acc: Self = 1;
let mut overflown = false;
Expand Down Expand Up @@ -3899,11 +3917,12 @@ Basic usage:
", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(5), 32);", $EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[rustc_inherit_overflow_checks]
pub fn pow(self, mut exp: u32) -> Self {
pub const fn pow(self, mut exp: u32) -> Self {
let mut base = self;
let mut acc = 1;

Expand Down Expand Up @@ -4014,7 +4033,8 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, "
// overflow cases it instead ends up returning the maximum value
// of the type, and can return 0 for 0.
#[inline]
fn one_less_than_next_power_of_two(self) -> Self {
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
const fn one_less_than_next_power_of_two(self) -> Self {
if self <= 1 { return 0; }

let p = self - 1;
Expand Down Expand Up @@ -4042,10 +4062,11 @@ Basic usage:
assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);", $EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
#[inline]
pub fn next_power_of_two(self) -> Self {
// Call the trait to get overflow checks
ops::Add::add(self.one_less_than_next_power_of_two(), 1)
#[rustc_inherit_overflow_checks]
pub const fn next_power_of_two(self) -> Self {
self.one_less_than_next_power_of_two() + 1
}
}

Expand All @@ -4067,7 +4088,8 @@ $EndFeature, "
```"),
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn checked_next_power_of_two(self) -> Option<Self> {
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
pub const fn checked_next_power_of_two(self) -> Option<Self> {
self.one_less_than_next_power_of_two().checked_add(1)
}
}
Expand All @@ -4091,7 +4113,8 @@ $EndFeature, "
```"),
#[unstable(feature = "wrapping_next_power_of_two", issue = "32463",
reason = "needs decision on wrapping behaviour")]
pub fn wrapping_next_power_of_two(self) -> Self {
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
pub const fn wrapping_next_power_of_two(self) -> Self {
self.one_less_than_next_power_of_two().wrapping_add(1)
}
}
Expand Down
30 changes: 23 additions & 7 deletions src/librustc_error_codes/error_codes/E0317.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
This error occurs when an `if` expression without an `else` block is used in a
context where a type other than `()` is expected, for example a `let`
expression:
An `if` expression is missing an `else` block.

Erroneous code example:

```compile_fail,E0317
fn main() {
let x = 5;
let a = if x == 5 { 1 };
}
let x = 5;
let a = if x == 5 {
1
};
```

This error occurs when an `if` expression without an `else` block is used in a
context where a type other than `()` is expected. In the previous code example,
the `let` expression was expecting a value but since there was no `else`, no
value was returned.

An `if` expression without an `else` block has the type `()`, so this is a type
error. To resolve it, add an `else` block having the same type as the `if`
block.

So to fix the previous code example:

```
let x = 5;
let a = if x == 5 {
1
} else {
2
};
```
10 changes: 4 additions & 6 deletions src/librustc_span/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1075,7 +1075,7 @@ impl SourceFile {
unmapped_path: FileName,
mut src: String,
start_pos: BytePos,
) -> Result<SourceFile, OffsetOverflowError> {
) -> Self {
let normalized_pos = normalize_src(&mut src, start_pos);

let src_hash = {
Expand All @@ -1089,14 +1089,12 @@ impl SourceFile {
hasher.finish::<u128>()
};
let end_pos = start_pos.to_usize() + src.len();
if end_pos > u32::max_value() as usize {
return Err(OffsetOverflowError);
}
assert!(end_pos <= u32::max_value() as usize);

let (lines, multibyte_chars, non_narrow_chars) =
analyze_source_file::analyze_source_file(&src[..], start_pos);

Ok(SourceFile {
SourceFile {
name,
name_was_remapped,
unmapped_path: Some(unmapped_path),
Expand All @@ -1111,7 +1109,7 @@ impl SourceFile {
non_narrow_chars,
normalized_pos,
name_hash,
})
}
}

/// Returns the `BytePos` of the beginning of the current line.
Expand Down
Loading

0 comments on commit 93711d0

Please sign in to comment.