Auto merge of #69309 - Dylan-DPC:rollup-gjdqx7l, r=Dylan-DPC
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
This commit is contained in:
commit
93711d063b
|
@ -878,6 +878,52 @@ impl<T> LinkedList<T> {
|
||||||
unsafe { self.split_off_after_node(split_node, at) }
|
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.
|
/// 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.
|
/// If the closure returns true, then the element is removed and yielded.
|
||||||
|
|
|
@ -73,11 +73,14 @@
|
||||||
#![feature(const_ascii_ctype_on_intrinsics)]
|
#![feature(const_ascii_ctype_on_intrinsics)]
|
||||||
#![feature(const_alloc_layout)]
|
#![feature(const_alloc_layout)]
|
||||||
#![feature(const_if_match)]
|
#![feature(const_if_match)]
|
||||||
|
#![feature(const_loop)]
|
||||||
#![feature(const_checked_int_methods)]
|
#![feature(const_checked_int_methods)]
|
||||||
#![feature(const_euclidean_int_methods)]
|
#![feature(const_euclidean_int_methods)]
|
||||||
#![feature(const_overflowing_int_methods)]
|
#![feature(const_overflowing_int_methods)]
|
||||||
#![feature(const_saturating_int_methods)]
|
#![feature(const_saturating_int_methods)]
|
||||||
#![feature(const_int_unchecked_arith)]
|
#![feature(const_int_unchecked_arith)]
|
||||||
|
#![feature(const_int_pow)]
|
||||||
|
#![feature(constctlz)]
|
||||||
#![feature(const_panic)]
|
#![feature(const_panic)]
|
||||||
#![feature(const_fn_union)]
|
#![feature(const_fn_union)]
|
||||||
#![feature(const_generics)]
|
#![feature(const_generics)]
|
||||||
|
|
|
@ -8,9 +8,18 @@ use crate::convert::Infallible;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::intrinsics;
|
use crate::intrinsics;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::ops;
|
|
||||||
use crate::str::FromStr;
|
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 {
|
macro_rules! impl_nonzero_fmt {
|
||||||
( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
|
( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
|
||||||
$(
|
$(
|
||||||
|
@ -993,26 +1002,27 @@ $EndFeature, "
|
||||||
```"),
|
```"),
|
||||||
|
|
||||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
#[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, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[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 base = self;
|
||||||
let mut acc: Self = 1;
|
let mut acc: Self = 1;
|
||||||
|
|
||||||
while exp > 1 {
|
while exp > 1 {
|
||||||
if (exp & 1) == 1 {
|
if (exp & 1) == 1 {
|
||||||
acc = acc.checked_mul(base)?;
|
acc = try_opt!(acc.checked_mul(base));
|
||||||
}
|
}
|
||||||
exp /= 2;
|
exp /= 2;
|
||||||
base = base.checked_mul(base)?;
|
base = try_opt!(base.checked_mul(base));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deal with the final bit of the exponent separately, since
|
// Deal with the final bit of the exponent separately, since
|
||||||
// squaring the base afterwards is not necessary and may cause a
|
// squaring the base afterwards is not necessary and may cause a
|
||||||
// needless overflow.
|
// needless overflow.
|
||||||
if exp == 1 {
|
if exp == 1 {
|
||||||
acc = acc.checked_mul(base)?;
|
acc = try_opt!(acc.checked_mul(base));
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(acc)
|
Some(acc)
|
||||||
|
@ -1180,10 +1190,11 @@ assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT
|
||||||
$EndFeature, "
|
$EndFeature, "
|
||||||
```"),
|
```"),
|
||||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
#[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, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn saturating_pow(self, exp: u32) -> Self {
|
pub const fn saturating_pow(self, exp: u32) -> Self {
|
||||||
match self.checked_pow(exp) {
|
match self.checked_pow(exp) {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
None if self < 0 && exp % 2 == 1 => Self::min_value(),
|
None if self < 0 && exp % 2 == 1 => Self::min_value(),
|
||||||
|
@ -1523,10 +1534,11 @@ assert_eq!(3i8.wrapping_pow(6), -39);",
|
||||||
$EndFeature, "
|
$EndFeature, "
|
||||||
```"),
|
```"),
|
||||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
#[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, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[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 base = self;
|
||||||
let mut acc: Self = 1;
|
let mut acc: Self = 1;
|
||||||
|
|
||||||
|
@ -1900,10 +1912,11 @@ assert_eq!(3i8.overflowing_pow(5), (-13, true));",
|
||||||
$EndFeature, "
|
$EndFeature, "
|
||||||
```"),
|
```"),
|
||||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
#[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, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[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 base = self;
|
||||||
let mut acc: Self = 1;
|
let mut acc: Self = 1;
|
||||||
let mut overflown = false;
|
let mut overflown = false;
|
||||||
|
@ -1949,11 +1962,12 @@ assert_eq!(x.pow(5), 32);",
|
||||||
$EndFeature, "
|
$EndFeature, "
|
||||||
```"),
|
```"),
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_inherit_overflow_checks]
|
#[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 base = self;
|
||||||
let mut acc = 1;
|
let mut acc = 1;
|
||||||
|
|
||||||
|
@ -3119,26 +3133,27 @@ Basic usage:
|
||||||
assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", $EndFeature, "
|
assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", $EndFeature, "
|
||||||
```"),
|
```"),
|
||||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
#[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, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[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 base = self;
|
||||||
let mut acc: Self = 1;
|
let mut acc: Self = 1;
|
||||||
|
|
||||||
while exp > 1 {
|
while exp > 1 {
|
||||||
if (exp & 1) == 1 {
|
if (exp & 1) == 1 {
|
||||||
acc = acc.checked_mul(base)?;
|
acc = try_opt!(acc.checked_mul(base));
|
||||||
}
|
}
|
||||||
exp /= 2;
|
exp /= 2;
|
||||||
base = base.checked_mul(base)?;
|
base = try_opt!(base.checked_mul(base));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deal with the final bit of the exponent separately, since
|
// Deal with the final bit of the exponent separately, since
|
||||||
// squaring the base afterwards is not necessary and may cause a
|
// squaring the base afterwards is not necessary and may cause a
|
||||||
// needless overflow.
|
// needless overflow.
|
||||||
if exp == 1 {
|
if exp == 1 {
|
||||||
acc = acc.checked_mul(base)?;
|
acc = try_opt!(acc.checked_mul(base));
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(acc)
|
Some(acc)
|
||||||
|
@ -3234,10 +3249,11 @@ assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT
|
||||||
$EndFeature, "
|
$EndFeature, "
|
||||||
```"),
|
```"),
|
||||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
#[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, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn saturating_pow(self, exp: u32) -> Self {
|
pub const fn saturating_pow(self, exp: u32) -> Self {
|
||||||
match self.checked_pow(exp) {
|
match self.checked_pow(exp) {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
None => Self::max_value(),
|
None => Self::max_value(),
|
||||||
|
@ -3527,10 +3543,11 @@ Basic usage:
|
||||||
assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, "
|
assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, "
|
||||||
```"),
|
```"),
|
||||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
#[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, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[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 base = self;
|
||||||
let mut acc: Self = 1;
|
let mut acc: Self = 1;
|
||||||
|
|
||||||
|
@ -3853,10 +3870,11 @@ Basic usage:
|
||||||
assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, "
|
assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, "
|
||||||
```"),
|
```"),
|
||||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
#[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, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[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 base = self;
|
||||||
let mut acc: Self = 1;
|
let mut acc: Self = 1;
|
||||||
let mut overflown = false;
|
let mut overflown = false;
|
||||||
|
@ -3899,11 +3917,12 @@ Basic usage:
|
||||||
", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(5), 32);", $EndFeature, "
|
", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(5), 32);", $EndFeature, "
|
||||||
```"),
|
```"),
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_inherit_overflow_checks]
|
#[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 base = self;
|
||||||
let mut acc = 1;
|
let mut acc = 1;
|
||||||
|
|
||||||
|
@ -4014,7 +4033,8 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, "
|
||||||
// overflow cases it instead ends up returning the maximum value
|
// overflow cases it instead ends up returning the maximum value
|
||||||
// of the type, and can return 0 for 0.
|
// of the type, and can return 0 for 0.
|
||||||
#[inline]
|
#[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; }
|
if self <= 1 { return 0; }
|
||||||
|
|
||||||
let p = self - 1;
|
let p = self - 1;
|
||||||
|
@ -4042,10 +4062,11 @@ Basic usage:
|
||||||
assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);", $EndFeature, "
|
assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);", $EndFeature, "
|
||||||
```"),
|
```"),
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn next_power_of_two(self) -> Self {
|
#[rustc_inherit_overflow_checks]
|
||||||
// Call the trait to get overflow checks
|
pub const fn next_power_of_two(self) -> Self {
|
||||||
ops::Add::add(self.one_less_than_next_power_of_two(), 1)
|
self.one_less_than_next_power_of_two() + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4067,7 +4088,8 @@ $EndFeature, "
|
||||||
```"),
|
```"),
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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)
|
self.one_less_than_next_power_of_two().checked_add(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4091,7 +4113,8 @@ $EndFeature, "
|
||||||
```"),
|
```"),
|
||||||
#[unstable(feature = "wrapping_next_power_of_two", issue = "32463",
|
#[unstable(feature = "wrapping_next_power_of_two", issue = "32463",
|
||||||
reason = "needs decision on wrapping behaviour")]
|
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)
|
self.one_less_than_next_power_of_two().wrapping_add(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,30 @@
|
||||||
This error occurs when an `if` expression without an `else` block is used in a
|
An `if` expression is missing an `else` block.
|
||||||
context where a type other than `()` is expected, for example a `let`
|
|
||||||
expression:
|
Erroneous code example:
|
||||||
|
|
||||||
```compile_fail,E0317
|
```compile_fail,E0317
|
||||||
fn main() {
|
let x = 5;
|
||||||
let x = 5;
|
let a = if x == 5 {
|
||||||
let a = if x == 5 { 1 };
|
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
|
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`
|
error. To resolve it, add an `else` block having the same type as the `if`
|
||||||
block.
|
block.
|
||||||
|
|
||||||
|
So to fix the previous code example:
|
||||||
|
|
||||||
|
```
|
||||||
|
let x = 5;
|
||||||
|
let a = if x == 5 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
2
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
|
@ -1075,7 +1075,7 @@ impl SourceFile {
|
||||||
unmapped_path: FileName,
|
unmapped_path: FileName,
|
||||||
mut src: String,
|
mut src: String,
|
||||||
start_pos: BytePos,
|
start_pos: BytePos,
|
||||||
) -> Result<SourceFile, OffsetOverflowError> {
|
) -> Self {
|
||||||
let normalized_pos = normalize_src(&mut src, start_pos);
|
let normalized_pos = normalize_src(&mut src, start_pos);
|
||||||
|
|
||||||
let src_hash = {
|
let src_hash = {
|
||||||
|
@ -1089,14 +1089,12 @@ impl SourceFile {
|
||||||
hasher.finish::<u128>()
|
hasher.finish::<u128>()
|
||||||
};
|
};
|
||||||
let end_pos = start_pos.to_usize() + src.len();
|
let end_pos = start_pos.to_usize() + src.len();
|
||||||
if end_pos > u32::max_value() as usize {
|
assert!(end_pos <= u32::max_value() as usize);
|
||||||
return Err(OffsetOverflowError);
|
|
||||||
}
|
|
||||||
|
|
||||||
let (lines, multibyte_chars, non_narrow_chars) =
|
let (lines, multibyte_chars, non_narrow_chars) =
|
||||||
analyze_source_file::analyze_source_file(&src[..], start_pos);
|
analyze_source_file::analyze_source_file(&src[..], start_pos);
|
||||||
|
|
||||||
Ok(SourceFile {
|
SourceFile {
|
||||||
name,
|
name,
|
||||||
name_was_remapped,
|
name_was_remapped,
|
||||||
unmapped_path: Some(unmapped_path),
|
unmapped_path: Some(unmapped_path),
|
||||||
|
@ -1111,7 +1109,7 @@ impl SourceFile {
|
||||||
non_narrow_chars,
|
non_narrow_chars,
|
||||||
normalized_pos,
|
normalized_pos,
|
||||||
name_hash,
|
name_hash,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `BytePos` of the beginning of the current line.
|
/// Returns the `BytePos` of the beginning of the current line.
|
||||||
|
|
|
@ -12,10 +12,12 @@ pub use crate::*;
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::stable_hasher::StableHasher;
|
use rustc_data_structures::stable_hasher::StableHasher;
|
||||||
use rustc_data_structures::sync::{Lock, LockGuard, Lrc, MappedLockGuard};
|
use rustc_data_structures::sync::{AtomicU32, Lock, LockGuard, Lrc, MappedLockGuard};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
@ -131,6 +133,9 @@ pub(super) struct SourceMapFiles {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SourceMap {
|
pub struct SourceMap {
|
||||||
|
/// The address space below this value is currently used by the files in the source map.
|
||||||
|
used_address_space: AtomicU32,
|
||||||
|
|
||||||
files: Lock<SourceMapFiles>,
|
files: Lock<SourceMapFiles>,
|
||||||
file_loader: Box<dyn FileLoader + Sync + Send>,
|
file_loader: Box<dyn FileLoader + Sync + Send>,
|
||||||
// This is used to apply the file path remapping as specified via
|
// This is used to apply the file path remapping as specified via
|
||||||
|
@ -140,14 +145,24 @@ pub struct SourceMap {
|
||||||
|
|
||||||
impl SourceMap {
|
impl SourceMap {
|
||||||
pub fn new(path_mapping: FilePathMapping) -> SourceMap {
|
pub fn new(path_mapping: FilePathMapping) -> SourceMap {
|
||||||
SourceMap { files: Default::default(), file_loader: Box::new(RealFileLoader), path_mapping }
|
SourceMap {
|
||||||
|
used_address_space: AtomicU32::new(0),
|
||||||
|
files: Default::default(),
|
||||||
|
file_loader: Box::new(RealFileLoader),
|
||||||
|
path_mapping,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_file_loader(
|
pub fn with_file_loader(
|
||||||
file_loader: Box<dyn FileLoader + Sync + Send>,
|
file_loader: Box<dyn FileLoader + Sync + Send>,
|
||||||
path_mapping: FilePathMapping,
|
path_mapping: FilePathMapping,
|
||||||
) -> SourceMap {
|
) -> SourceMap {
|
||||||
SourceMap { files: Default::default(), file_loader, path_mapping }
|
SourceMap {
|
||||||
|
used_address_space: AtomicU32::new(0),
|
||||||
|
files: Default::default(),
|
||||||
|
file_loader,
|
||||||
|
path_mapping,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn path_mapping(&self) -> &FilePathMapping {
|
pub fn path_mapping(&self) -> &FilePathMapping {
|
||||||
|
@ -194,12 +209,25 @@ impl SourceMap {
|
||||||
self.files.borrow().stable_id_to_source_file.get(&stable_id).map(|sf| sf.clone())
|
self.files.borrow().stable_id_to_source_file.get(&stable_id).map(|sf| sf.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_start_pos(&self) -> usize {
|
fn allocate_address_space(&self, size: usize) -> Result<usize, OffsetOverflowError> {
|
||||||
match self.files.borrow().source_files.last() {
|
let size = u32::try_from(size).map_err(|_| OffsetOverflowError)?;
|
||||||
None => 0,
|
|
||||||
// Add one so there is some space between files. This lets us distinguish
|
loop {
|
||||||
// positions in the `SourceMap`, even in the presence of zero-length files.
|
let current = self.used_address_space.load(Ordering::Relaxed);
|
||||||
Some(last) => last.end_pos.to_usize() + 1,
|
let next = current
|
||||||
|
.checked_add(size)
|
||||||
|
// Add one so there is some space between files. This lets us distinguish
|
||||||
|
// positions in the `SourceMap`, even in the presence of zero-length files.
|
||||||
|
.and_then(|next| next.checked_add(1))
|
||||||
|
.ok_or(OffsetOverflowError)?;
|
||||||
|
|
||||||
|
if self
|
||||||
|
.used_address_space
|
||||||
|
.compare_exchange(current, next, Ordering::Relaxed, Ordering::Relaxed)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
return Ok(usize::try_from(current).unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,8 +246,6 @@ impl SourceMap {
|
||||||
filename: FileName,
|
filename: FileName,
|
||||||
src: String,
|
src: String,
|
||||||
) -> Result<Lrc<SourceFile>, OffsetOverflowError> {
|
) -> Result<Lrc<SourceFile>, OffsetOverflowError> {
|
||||||
let start_pos = self.next_start_pos();
|
|
||||||
|
|
||||||
// The path is used to determine the directory for loading submodules and
|
// The path is used to determine the directory for loading submodules and
|
||||||
// include files, so it must be before remapping.
|
// include files, so it must be before remapping.
|
||||||
// Note that filename may not be a valid path, eg it may be `<anon>` etc,
|
// Note that filename may not be a valid path, eg it may be `<anon>` etc,
|
||||||
|
@ -241,13 +267,15 @@ impl SourceMap {
|
||||||
let lrc_sf = match self.source_file_by_stable_id(file_id) {
|
let lrc_sf = match self.source_file_by_stable_id(file_id) {
|
||||||
Some(lrc_sf) => lrc_sf,
|
Some(lrc_sf) => lrc_sf,
|
||||||
None => {
|
None => {
|
||||||
|
let start_pos = self.allocate_address_space(src.len())?;
|
||||||
|
|
||||||
let source_file = Lrc::new(SourceFile::new(
|
let source_file = Lrc::new(SourceFile::new(
|
||||||
filename,
|
filename,
|
||||||
was_remapped,
|
was_remapped,
|
||||||
unmapped_path,
|
unmapped_path,
|
||||||
src,
|
src,
|
||||||
Pos::from_usize(start_pos),
|
Pos::from_usize(start_pos),
|
||||||
)?);
|
));
|
||||||
|
|
||||||
let mut files = self.files.borrow_mut();
|
let mut files = self.files.borrow_mut();
|
||||||
|
|
||||||
|
@ -277,7 +305,9 @@ impl SourceMap {
|
||||||
mut file_local_non_narrow_chars: Vec<NonNarrowChar>,
|
mut file_local_non_narrow_chars: Vec<NonNarrowChar>,
|
||||||
mut file_local_normalized_pos: Vec<NormalizedPos>,
|
mut file_local_normalized_pos: Vec<NormalizedPos>,
|
||||||
) -> Lrc<SourceFile> {
|
) -> Lrc<SourceFile> {
|
||||||
let start_pos = self.next_start_pos();
|
let start_pos = self
|
||||||
|
.allocate_address_space(source_len)
|
||||||
|
.expect("not enough address space for imported source file");
|
||||||
|
|
||||||
let end_pos = Pos::from_usize(start_pos + source_len);
|
let end_pos = Pos::from_usize(start_pos + source_len);
|
||||||
let start_pos = Pos::from_usize(start_pos);
|
let start_pos = Pos::from_usize(start_pos);
|
||||||
|
|
|
@ -331,14 +331,14 @@ impl Once {
|
||||||
/// * `call_once` was called, but has not yet completed,
|
/// * `call_once` was called, but has not yet completed,
|
||||||
/// * the `Once` instance is poisoned
|
/// * the `Once` instance is poisoned
|
||||||
///
|
///
|
||||||
/// It is also possible that immediately after `is_completed`
|
/// This function returning `false` does not mean that `Once` has not been
|
||||||
/// returns false, some other thread finishes executing
|
/// executed. For example, it may have been executed in the time between
|
||||||
/// `call_once`.
|
/// when `is_completed` starts executing and when it returns, in which case
|
||||||
|
/// the `false` return value would be stale (but still permissible).
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(once_is_completed)]
|
|
||||||
/// use std::sync::Once;
|
/// use std::sync::Once;
|
||||||
///
|
///
|
||||||
/// static INIT: Once = Once::new();
|
/// static INIT: Once = Once::new();
|
||||||
|
@ -351,7 +351,6 @@ impl Once {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(once_is_completed)]
|
|
||||||
/// use std::sync::Once;
|
/// use std::sync::Once;
|
||||||
/// use std::thread;
|
/// use std::thread;
|
||||||
///
|
///
|
||||||
|
@ -364,7 +363,7 @@ impl Once {
|
||||||
/// assert!(handle.join().is_err());
|
/// assert!(handle.join().is_err());
|
||||||
/// assert_eq!(INIT.is_completed(), false);
|
/// assert_eq!(INIT.is_completed(), false);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "once_is_completed", issue = "54890")]
|
#[stable(feature = "once_is_completed", since = "1.44.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_completed(&self) -> bool {
|
pub fn is_completed(&self) -> bool {
|
||||||
// An `Acquire` load is enough because that makes all the initialization
|
// An `Acquire` load is enough because that makes all the initialization
|
||||||
|
|
|
@ -1,11 +1,48 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(const_int_pow)]
|
||||||
|
#![feature(wrapping_next_power_of_two)]
|
||||||
|
|
||||||
const IS_POWER_OF_TWO_A: bool = 0u32.is_power_of_two();
|
const IS_POWER_OF_TWO_A: bool = 0u32.is_power_of_two();
|
||||||
const IS_POWER_OF_TWO_B: bool = 32u32.is_power_of_two();
|
const IS_POWER_OF_TWO_B: bool = 32u32.is_power_of_two();
|
||||||
const IS_POWER_OF_TWO_C: bool = 33u32.is_power_of_two();
|
const IS_POWER_OF_TWO_C: bool = 33u32.is_power_of_two();
|
||||||
|
|
||||||
|
const POW: u8 = 3u8.pow(5);
|
||||||
|
|
||||||
|
const CHECKED_POW_OK: Option<u8> = 3u8.checked_pow(5);
|
||||||
|
const CHECKED_POW_OVERFLOW: Option<u8> = 3u8.checked_pow(6);
|
||||||
|
|
||||||
|
const WRAPPING_POW: u8 = 3u8.wrapping_pow(6);
|
||||||
|
const OVERFLOWING_POW: (u8, bool) = 3u8.overflowing_pow(6);
|
||||||
|
const SATURATING_POW: u8 = 3u8.saturating_pow(6);
|
||||||
|
|
||||||
|
const NEXT_POWER_OF_TWO: u32 = 3u32.next_power_of_two();
|
||||||
|
|
||||||
|
const CHECKED_NEXT_POWER_OF_TWO_OK: Option<u32> = 3u32.checked_next_power_of_two();
|
||||||
|
const CHECKED_NEXT_POWER_OF_TWO_OVERFLOW: Option<u32> =
|
||||||
|
u32::max_value().checked_next_power_of_two();
|
||||||
|
|
||||||
|
const WRAPPING_NEXT_POWER_OF_TWO: u32 =
|
||||||
|
u32::max_value().wrapping_next_power_of_two();
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
assert!(!IS_POWER_OF_TWO_A);
|
assert!(!IS_POWER_OF_TWO_A);
|
||||||
assert!(IS_POWER_OF_TWO_B);
|
assert!(IS_POWER_OF_TWO_B);
|
||||||
assert!(!IS_POWER_OF_TWO_C);
|
assert!(!IS_POWER_OF_TWO_C);
|
||||||
|
|
||||||
|
assert_eq!(POW, 243);
|
||||||
|
|
||||||
|
assert_eq!(CHECKED_POW_OK, Some(243));
|
||||||
|
assert_eq!(CHECKED_POW_OVERFLOW, None);
|
||||||
|
|
||||||
|
assert_eq!(WRAPPING_POW, 217);
|
||||||
|
assert_eq!(OVERFLOWING_POW, (217, true));
|
||||||
|
assert_eq!(SATURATING_POW, u8::max_value());
|
||||||
|
|
||||||
|
assert_eq!(NEXT_POWER_OF_TWO, 4);
|
||||||
|
|
||||||
|
assert_eq!(CHECKED_NEXT_POWER_OF_TWO_OK, Some(4));
|
||||||
|
assert_eq!(CHECKED_NEXT_POWER_OF_TWO_OVERFLOW, None);
|
||||||
|
|
||||||
|
assert_eq!(WRAPPING_NEXT_POWER_OF_TWO, 0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue