diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index b88ca8a0fb0..f8f987efeb8 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -878,6 +878,52 @@ impl LinkedList { 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. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 12647fae900..bca96b77812 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -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)] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 471ab966622..6f55e7c8be8 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -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 ) => { $( @@ -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 { + pub const fn checked_pow(self, mut exp: u32) -> Option { 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) @@ -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(), @@ -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; @@ -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; @@ -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; @@ -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 { + pub const fn checked_pow(self, mut exp: u32) -> Option { 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) @@ -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(), @@ -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; @@ -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; @@ -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; @@ -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; @@ -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 } } @@ -4067,7 +4088,8 @@ $EndFeature, " ```"), #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn checked_next_power_of_two(self) -> Option { + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + pub const fn checked_next_power_of_two(self) -> Option { 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", 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) } } diff --git a/src/librustc_error_codes/error_codes/E0317.md b/src/librustc_error_codes/error_codes/E0317.md index e31a2b56be3..230911c2086 100644 --- a/src/librustc_error_codes/error_codes/E0317.md +++ b/src/librustc_error_codes/error_codes/E0317.md @@ -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 +}; +``` diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 8f00b76001f..f9f3a900311 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -1075,7 +1075,7 @@ impl SourceFile { unmapped_path: FileName, mut src: String, start_pos: BytePos, - ) -> Result { + ) -> Self { let normalized_pos = normalize_src(&mut src, start_pos); let src_hash = { @@ -1089,14 +1089,12 @@ impl SourceFile { hasher.finish::() }; 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), @@ -1111,7 +1109,7 @@ impl SourceFile { non_narrow_chars, normalized_pos, name_hash, - }) + } } /// Returns the `BytePos` of the beginning of the current line. diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index 45c4d6dbc6c..31d397f040c 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -12,10 +12,12 @@ pub use crate::*; use rustc_data_structures::fx::FxHashMap; 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::convert::TryFrom; use std::hash::Hash; use std::path::{Path, PathBuf}; +use std::sync::atomic::Ordering; use log::debug; use std::env; @@ -131,6 +133,9 @@ pub(super) struct SourceMapFiles { } 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, file_loader: Box, // This is used to apply the file path remapping as specified via @@ -140,14 +145,24 @@ pub struct SourceMap { impl 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( file_loader: Box, path_mapping: FilePathMapping, ) -> 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 { @@ -194,12 +209,25 @@ impl SourceMap { self.files.borrow().stable_id_to_source_file.get(&stable_id).map(|sf| sf.clone()) } - fn next_start_pos(&self) -> usize { - match self.files.borrow().source_files.last() { - None => 0, - // 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. - Some(last) => last.end_pos.to_usize() + 1, + fn allocate_address_space(&self, size: usize) -> Result { + let size = u32::try_from(size).map_err(|_| OffsetOverflowError)?; + + loop { + let current = self.used_address_space.load(Ordering::Relaxed); + 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, src: String, ) -> Result, OffsetOverflowError> { - let start_pos = self.next_start_pos(); - // The path is used to determine the directory for loading submodules and // include files, so it must be before remapping. // Note that filename may not be a valid path, eg it may be `` etc, @@ -241,13 +267,15 @@ impl SourceMap { let lrc_sf = match self.source_file_by_stable_id(file_id) { Some(lrc_sf) => lrc_sf, None => { + let start_pos = self.allocate_address_space(src.len())?; + let source_file = Lrc::new(SourceFile::new( filename, was_remapped, unmapped_path, src, Pos::from_usize(start_pos), - )?); + )); let mut files = self.files.borrow_mut(); @@ -277,7 +305,9 @@ impl SourceMap { mut file_local_non_narrow_chars: Vec, mut file_local_normalized_pos: Vec, ) -> Lrc { - 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 start_pos = Pos::from_usize(start_pos); diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 61c4d0c2dbf..b99b4d8d9fd 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -331,14 +331,14 @@ impl Once { /// * `call_once` was called, but has not yet completed, /// * the `Once` instance is poisoned /// - /// It is also possible that immediately after `is_completed` - /// returns false, some other thread finishes executing - /// `call_once`. + /// This function returning `false` does not mean that `Once` has not been + /// executed. For example, it may have been executed in the time between + /// when `is_completed` starts executing and when it returns, in which case + /// the `false` return value would be stale (but still permissible). /// /// # Examples /// /// ``` - /// #![feature(once_is_completed)] /// use std::sync::Once; /// /// static INIT: Once = Once::new(); @@ -351,7 +351,6 @@ impl Once { /// ``` /// /// ``` - /// #![feature(once_is_completed)] /// use std::sync::Once; /// use std::thread; /// @@ -364,7 +363,7 @@ impl Once { /// assert!(handle.join().is_err()); /// assert_eq!(INIT.is_completed(), false); /// ``` - #[unstable(feature = "once_is_completed", issue = "54890")] + #[stable(feature = "once_is_completed", since = "1.44.0")] #[inline] pub fn is_completed(&self) -> bool { // An `Acquire` load is enough because that makes all the initialization diff --git a/src/test/ui/consts/const-int-pow-rpass.rs b/src/test/ui/consts/const-int-pow-rpass.rs index 8e84a900605..b0fba19455b 100644 --- a/src/test/ui/consts/const-int-pow-rpass.rs +++ b/src/test/ui/consts/const-int-pow-rpass.rs @@ -1,11 +1,48 @@ // 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_B: bool = 32u32.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 = 3u8.checked_pow(5); +const CHECKED_POW_OVERFLOW: Option = 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 = 3u32.checked_next_power_of_two(); +const CHECKED_NEXT_POWER_OF_TWO_OVERFLOW: Option = + 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() { assert!(!IS_POWER_OF_TWO_A); assert!(IS_POWER_OF_TWO_B); 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); }