Skip to content

Commit 6d7a5e7

Browse files
committed
rollup merge of #22455: msiemens/add-vec-from_elem
Implement `Vec::from_elem` by making the `vec![element; len]` macro more powerful (see rust-lang/rfcs#832). Closes #22414 r? @gankro
2 parents f10f7f5 + 2bf553c commit 6d7a5e7

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

src/libcollections/macros.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,34 @@
99
// except according to those terms.
1010

1111
/// Creates a `Vec` containing the arguments.
12+
///
13+
/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions.
14+
/// There are two forms of this macro:
15+
///
16+
/// - Create a `Vec` containing a given list of elements:
17+
///
18+
/// ```
19+
/// let v = vec![1, 2, 3];
20+
/// assert_eq!(v[0], 1);
21+
/// assert_eq!(v[1], 2);
22+
/// assert_eq!(v[2], 3);
23+
/// ```
24+
///
25+
/// - Create a `Vec` from a given element and size:
26+
///
27+
/// ```
28+
/// let v = vec![1; 3];
29+
/// assert_eq!(v, vec![1, 1, 1]);
30+
/// ```
31+
///
32+
/// Note that unlike array expressions this syntax supports all elements
33+
/// which implement `Clone` and the number of elements doesn't have to be
34+
/// a constant.
1235
#[macro_export]
1336
#[stable(feature = "rust1", since = "1.0.0")]
1437
macro_rules! vec {
15-
($x:expr; $y:expr) => (
16-
<[_] as $crate::slice::SliceExt>::into_vec(
17-
$crate::boxed::Box::new([$x; $y]))
38+
($elem:expr; $n:expr) => (
39+
$crate::vec::from_elem($elem, $n)
1840
);
1941
($($x:expr),*) => (
2042
<[_] as $crate::slice::SliceExt>::into_vec(

src/libcollections/vec.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,30 @@ unsafe fn dealloc<T>(ptr: *mut T, len: usize) {
12521252
}
12531253
}
12541254

1255+
#[doc(hidden)]
1256+
#[stable(feature = "rust1", since = "1.0.0")]
1257+
pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
1258+
unsafe {
1259+
let mut v = Vec::with_capacity(n);
1260+
let mut ptr = v.as_mut_ptr();
1261+
1262+
// Write all elements except the last one
1263+
for i in 1..n {
1264+
ptr::write(ptr, Clone::clone(&elem));
1265+
ptr = ptr.offset(1);
1266+
v.set_len(i); // Increment the length in every step in case Clone::clone() panics
1267+
}
1268+
1269+
if n > 0 {
1270+
// We can write the last element directly without cloning needlessly
1271+
ptr::write(ptr, elem);
1272+
v.set_len(n);
1273+
}
1274+
1275+
v
1276+
}
1277+
}
1278+
12551279
////////////////////////////////////////////////////////////////////////////////
12561280
// Common trait implementations for Vec
12571281
////////////////////////////////////////////////////////////////////////////////

src/test/run-pass/vec-macro-repeat.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,9 @@ pub fn main() {
1414
assert_eq!(vec![1; 2], vec![1, 1]);
1515
assert_eq!(vec![1; 1], vec![1]);
1616
assert_eq!(vec![1; 0], vec![]);
17+
18+
// from_elem syntax (see RFC 832)
19+
let el = Box::new(1);
20+
let n = 3;
21+
assert_eq!(vec![el; n], vec![Box::new(1), Box::new(1), Box::new(1)]);
1722
}

0 commit comments

Comments
 (0)