diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 2adce8d270398..d2bc5d9bce39d 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -745,6 +745,59 @@ impl Vec { unsafe { Self::from_parts_in(ptr, length, capacity, Global) } } + /// Creates a `Vec` where each element is produced by calling `f` with + /// that element's index while walking forward through the `Vec`. + /// + /// This is essentially the same as writing + /// + /// ```text + /// vec![f(0), f(1), f(2), …, f(length - 2), f(length - 1)] + /// ``` + /// and is similar to `(0..i).map(f)`, just for `Vec`s not iterators. + /// + /// If `length == 0`, this produces an empty `Vec` without ever calling `f`. + /// + /// # Example + /// + /// ```rust + /// #![feature(vec_from_fn)] + /// + /// let vec = Vec::from_fn(5, |i| i); + /// + /// // indexes are: 0 1 2 3 4 + /// assert_eq!(vec, [0, 1, 2, 3, 4]); + /// + /// let vec2 = Vec::from_fn(8, |i| i * 2); + /// + /// // indexes are: 0 1 2 3 4 5 6 7 + /// assert_eq!(vec2, [0, 2, 4, 6, 8, 10, 12, 14]); + /// + /// let bool_vec = Vec::from_fn(5, |i| i % 2 == 0); + /// + /// // indexes are: 0 1 2 3 4 + /// assert_eq!(bool_vec, [true, false, true, false, true]); + /// ``` + /// + /// The `Vec` is generated in ascending index order, starting from the front + /// and going towards the back, so you can use closures with mutable state: + /// ``` + /// #![feature(vec_from_fn)] + /// + /// let mut state = 1; + /// let a = Vec::from_fn(6, |_| { let x = state; state *= 2; x }); + /// + /// assert_eq!(a, [1, 2, 4, 8, 16, 32]); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[unstable(feature = "vec_from_fn", reason = "new API", issue = "149698")] + pub fn from_fn(length: usize, f: F) -> Self + where + F: FnMut(usize) -> T, + { + (0..length).map(f).collect() + } + /// Decomposes a `Vec` into its raw components: `(pointer, length, capacity)`. /// /// Returns the raw pointer to the underlying data, the length of diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr index dc2f6f66437e0..0dec424555ed5 100644 --- a/tests/ui/suggestions/deref-path-method.stderr +++ b/tests/ui/suggestions/deref-path-method.stderr @@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec<_, _>` consider using one of the foll Vec::::with_capacity Vec::::try_with_capacity Vec::::from_raw_parts - and 6 others + and 7 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: the function `contains` is implemented on `[_]` | diff --git a/tests/ui/ufcs/bad-builder.stderr b/tests/ui/ufcs/bad-builder.stderr index a3528cb1e7d80..2504a3d09253c 100644 --- a/tests/ui/ufcs/bad-builder.stderr +++ b/tests/ui/ufcs/bad-builder.stderr @@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec` consider using one of the followi Vec::::with_capacity Vec::::try_with_capacity Vec::::from_raw_parts - and 6 others + and 7 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: there is an associated function `new` with a similar name |