Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 245a28e

Browse files
committed
Support vec![const { ... }; n] syntax
1 parent 124eb96 commit 245a28e

File tree

4 files changed

+78
-0
lines changed

4 files changed

+78
-0
lines changed

‎library/alloc/src/macros.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ macro_rules! vec {
4343
() => (
4444
$crate::vec::Vec::new()
4545
);
46+
(const $elem:block; $n:expr) => (
47+
// SAFETY: The `const` keyword asserts the value being the result of a const expression.
48+
unsafe { $crate::vec::from_const_elem(const $elem, $n) }
49+
);
4650
($elem:expr; $n:expr) => (
4751
$crate::vec::from_elem($elem, $n)
4852
);

‎library/alloc/src/vec/mod.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3183,6 +3183,57 @@ pub fn from_elem_in<T: Clone, A: Allocator>(elem: T, n: usize, alloc: A) -> Vec<
31833183
<T as SpecFromElem>::from_elem(elem, n, alloc)
31843184
}
31853185

3186+
/// # Safety
3187+
///
3188+
/// `value` must points to a valid `T` value that is the result of some const expression.
3189+
unsafe fn fill_const_value<T>(buffer: &mut [MaybeUninit<T>], value: *const T) {
3190+
for target in buffer {
3191+
// SAFETY: If `value` is the result of some const expression, we can make as many copies as
3192+
// needed.
3193+
unsafe { target.write(ptr::read(value)) };
3194+
}
3195+
}
3196+
3197+
/// # Safety
3198+
///
3199+
/// `elem` must be the result of some const expression.
3200+
#[doc(hidden)]
3201+
#[cfg(not(no_global_oom_handling))]
3202+
#[unstable(feature = "vec_of_const_expr", issue = "none")]
3203+
#[track_caller]
3204+
pub unsafe fn from_const_elem<T>(elem: T, n: usize) -> Vec<T> {
3205+
// SAFETY: Caller has guaranteed `elem` being the result of some const expression.
3206+
unsafe { from_const_elem_in(elem, n, Global) }
3207+
}
3208+
3209+
/// # Safety
3210+
///
3211+
/// `elem` must be the result of some const expression.
3212+
#[doc(hidden)]
3213+
#[cfg(not(no_global_oom_handling))]
3214+
#[unstable(feature = "vec_of_const_expr", issue = "none")]
3215+
#[track_caller]
3216+
unsafe fn from_const_elem_in<T, A: Allocator>(elem: T, n: usize, alloc: A) -> Vec<T, A> {
3217+
// Avoid calling the destructor of `elem`.
3218+
let elem = ManuallyDrop::new(elem);
3219+
let elem_ptr = ptr::from_ref(&*elem);
3220+
let mut result = Vec::<T, A>::with_capacity_in(n, alloc);
3221+
let buffer_ptr = result.as_mut_ptr().cast::<MaybeUninit<T>>();
3222+
3223+
// SAFETY: `with_capacity_in` makes sure the capacity is at least `n`, so we can make a buffer
3224+
// of length `n` out of it.
3225+
let buffer = unsafe { slice::from_raw_parts_mut(buffer_ptr, n) };
3226+
3227+
// SAFETY: Caller has guaranteed `elem` being the result of some const expression.
3228+
unsafe { fill_const_value(buffer, elem_ptr) };
3229+
3230+
// SAFETY: We have initialized exactly `n` values at the start of the buffer, so we are safe to
3231+
// set the length accordingly.
3232+
unsafe { result.set_len(n) };
3233+
3234+
result
3235+
}
3236+
31863237
#[cfg(not(no_global_oom_handling))]
31873238
trait ExtendFromWithinSpec {
31883239
/// # Safety

‎library/alloc/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))]
3737
#![feature(drain_keep_rest)]
3838
#![feature(local_waker)]
39+
#![feature(vec_of_const_expr)]
3940
#![feature(vec_pop_if)]
4041
#![feature(unique_rc_arc)]
4142
#![feature(macro_metavar_expr_concat)]

‎library/alloc/tests/vec.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2311,6 +2311,28 @@ fn test_vec_macro_repeat() {
23112311
assert_eq!(vec![el; n], vec![Box::new(1), Box::new(1), Box::new(1)]);
23122312
}
23132313

2314+
#[test]
2315+
fn test_vec_macro_repeat_const() {
2316+
#[derive(Eq, PartialEq, Debug)]
2317+
struct Item {
2318+
x: u64,
2319+
y: u32, // Paddings are added to test the uninitialized bytes case.
2320+
}
2321+
2322+
impl Clone for Item {
2323+
fn clone(&self) -> Self {
2324+
panic!("no clone should be called");
2325+
}
2326+
}
2327+
2328+
const ITEM: Item = Item { x: 2, y: 3 };
2329+
2330+
assert_eq!(vec![const { ITEM }; 0], vec![ITEM; 0]);
2331+
assert_eq!(vec![const { ITEM }; 1], vec![ITEM]);
2332+
assert_eq!(vec![const { ITEM }; 2], vec![ITEM, ITEM]);
2333+
assert_eq!(vec![const { ITEM }; 3], vec![ITEM, ITEM, ITEM]);
2334+
}
2335+
23142336
#[test]
23152337
fn test_vec_swap() {
23162338
let mut a: Vec<isize> = vec![0, 1, 2, 3, 4, 5, 6];

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /