Skip to content

Rollup of 5 pull requests #69308

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

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
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