You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Provides the common use-case of creating custom fallible arrays in a reliable and unified way. Particularly useful for elements that don't implement Copy, Clone or Default.
I am not certain the currently implemented signature of try_from_fn is the right one. The most similar thing to this currently in the standard library is https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.try_for_each, where the return type is a generic R based on a Try trait impl, instead of hardcoded to Result. Can try_from_fn be done the same way?
It's easy to ignore it if you don't need it, like in array::from_fn(|_| value.clone()).
But tracking it yourself if the function doesn't when you do need it is a pain. ι being from_fn(identity) is so much tidier than { let mut i = 0; from_fn(|| { let temp = i; i += 1; temp }) } or whatever.
Unlike with iter::from_fn, a usize fundamentally can't overflow in array::from_fn. And iter::from_fn's closure must return an Option, so its signature will never match array::from_fn. (Though I guess array::try_from_fn can take -> Option closures, but with different semantics.)
Making it generic opens so many questions (like overflow) that I just don't see it happening in core. It could be done with Default + Step, but that's arguably a misuse of Default, and it also allows things like array::from_fn::<i8, 200> which feels wrong. I don't see core importing num_traits::Unsigned any time soon.
Making it generic would make it harder to ignore when you don't need it. It would be a shame to have to write array::from_fn(|_: usize| value.clone()), for example. It could potentially allow from_fn(|()| value.clone()), but that's non-obvious and makes the trait question even harder. (().. isn't an iterator, and I hope that stays the case.)
enumerate is precedent for "sometimes we only offer the usize version", so it's not unusual to only support usize here.
With TryInto in the prelude it's not that bad to get another type, and the range is obvious to LLVM in the monomorphization, so the checks easily optimize away.
It's almost certainly free to have the index. It's actually being maintained in the guard in collect_into_arrayanyway to know which things to drop. Not to mention that it has to write into the array, where if that's done with addressing modes like ptr [edx + 4*eax] then the counter's already there too. (And things'll probably get inlined enough anyway that it'd be easy to remove if unused. The only way it wouldn't would be if the closure if complex, but then the cost of 1 LEA is unnoticeable.)
So personally I think array::from_fn is right how it is, for all the reasons it ended up this way in the initial PR. And I'd like to see it move forward for stabilization. That's not up to me, though.
I don't think array::try_from_fn is ready yet, though, so I don't know how procedurally libs-api would like to go, here. Usually it FCPs in the tracking issue, but there can only be one FCP per issue/PR, so maybe for a partial one it'd need a separate issue or a stabilization PR in which to make the decision?
Reacted by Caio, Dominik Stolz, Sunjay Varma and Demian Ferreiro
I hate to re-bikeshed, but I stumbled on a possibility which I didn't see mentioned in #75644
I'm making a PR for array::repeat, to handle simple things like @leonardo-m's repeat(vec![]). But in doing that I noticed that there's not only iter::repeat -- which I was copying for array::repeat -- but there's also iter::repeat_with.
So I went to make array::repeat_with, but of course it's essentially identical to this tracking issue's array::from_fn. It's a much better parallel than iter::from_fn, as iter::repeat_with returns an "infinite" iterator and thus the closure is just -> Item (not from_fn's -> Option<Item>), like how the closure for creating an array is -> Element.
So a potential new coat of paint for the constructors could be
array::repeat for creating by cloning, like repeat(vec![1]).
array::repeat_with for creating by calling a closure, like repeat_with(|| Vec::with_capacity(10)).
array::try_repeat_with for creating by a fallible closure.
I don't know if this makes me feel differently about the usize argument. Allowing repeat_with(VecDeque::new) does feel somewhat more expected to me than from_fn(VecDeque::new), but I also still agree with the arguments in my previous comment. Of course, having both is also a possibility -- just like there's both iter::from_fn and iter::repeat_with, despite them being rather similar. Perhaps for nightly it would be reasonable to have both, with notes on their tracking issues to think about the other one if considering for stabilization?
The two most important things about these functions are (1) Provide an unified way for creating custom arrays (it is common enough for std) and (2) Take off the user burden of having to deal with unsafe.
That said, I will personally support any proposal that will move any function or method towards stabilization as soon as possible. So if desired feel free to create repeat-like variants, maintain both versions or even close this issue.
Although some recent development is happening in this field, sometimes I think that custom array constructors will take, if ever, as long as try_reserve or more.
fnconcat_arrs<T,constN:usize,constM:usize>(a:&mut([T;N],[T;M])) -> &mut[T;N + M];// Without coping, same for 3-tuples, 4-tuples, etcfnconcat_arr_of_arrs<T,constN:usize,constM:usize>(a:&mut[[T;N];M]) -> &mut[T;N*M];
As @scottmcm said, it is necessary to have stable constant closures in order to "constify" array::from_fn in stable toolchains, which is probably going to happen in the next few years or so. See #106003.
I think it is already possible to at least "constify" the hidden underlying machinery but I am not totally sure.
letmut parts = "Mary had a small lamp".split_ascii_whitespace();let parts:[&str;5] = from_fn(|_i| parts.next().unwrap());// produces: ["Mary", "had", "a", "small", "lamp"]
This works, but the documentation doesn't state that the callback parameter will grow upwards, so I'm not confident to use this code.
One day this could end up producing ["lamp", "small", "a", "had", "Mary"], if the implementation decided to "push" values from right to left, with a cb param going from 4 to zero; nothing says otherwise in the doc.
Is it possible that one day, we need the callback parameter to go in decreasing order?
If not, I think it would be nice to add a word about this in the documentation.
Reacted by Xiretza, Edgar Onghena, Elichai Turkel, vkontrimas, Tim Vilgot Mikael Fredenberg, Ronno Das, Noam Raz, Louis Saglio, Yokinman, MiSawa and 1 more
let mut parts = "Mary had a small lamp".split_ascii_whitespace();
let parts: [&str; 5] = from_fn(|_i| parts.next().unwrap());
// produces: ["Mary", "had", "a", "small", "lamp"]
This works, but the documentation doesn't state that the callback parameter will grow upwards, so I'm not confident to use this code. One day this could end up producing ["lamp", "small", "a", "had", "Mary"], if the implementation decided to "push" values from right to left, with a cb param going from 4 to zero; nothing says otherwise in the doc.
Is it possible that one day, we need the callback parameter to go in decreasing order? If not, I think it would be nice to add a word about this in the documentation.
Noticed that the ascending order is now guaranteed in Rust 1.88 🎉 #139061
Activity
dtolnay commentedon Nov 2, 2021
I am not certain the currently implemented signature of
try_from_fnis the right one. The most similar thing to this currently in the standard library is https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.try_for_each, where the return type is a genericRbased on aTrytrait impl, instead of hardcoded toResult. Cantry_from_fnbe done the same way?scottmcm commentedon Nov 27, 2021
@dtolnay I've submitted a PR to update
array::try_from_fnto be generic overTrytypes: #91286(As well as other related methods like
Iterator::try_find#63178 that hit similar questions.)scottmcm commentedon Nov 28, 2021
My 2¢ on the
usizeparameter question:array_from_fnsignatures #90505 (comment)array::from_fn(|_| value.clone()).ιbeingfrom_fn(identity)is so much tidier than{ let mut i = 0; from_fn(|| { let temp = i; i += 1; temp }) }or whatever.iter::from_fn, ausizefundamentally can't overflow inarray::from_fn. Anditer::from_fn's closure must return anOption, so its signature will never matcharray::from_fn. (Though I guessarray::try_from_fncan take-> Optionclosures, but with different semantics.)core. It could be done withDefault + Step, but that's arguably a misuse ofDefault, and it also allows things likearray::from_fn::<i8, 200>which feels wrong. I don't seecoreimportingnum_traits::Unsignedany time soon.array::from_fn(|_: usize| value.clone()), for example. It could potentially allowfrom_fn(|()| value.clone()), but that's non-obvious and makes the trait question even harder. (()..isn't an iterator, and I hope that stays the case.)enumerateis precedent for "sometimes we only offer theusizeversion", so it's not unusual to only supportusizehere.TryIntoin the prelude it's not that bad to get another type, and the range is obvious to LLVM in the monomorphization, so the checks easily optimize away.collect_into_arrayanyway to know which things to drop. Not to mention that it has to write into the array, where if that's done with addressing modes likeptr [edx + 4*eax]then the counter's already there too. (And things'll probably get inlined enough anyway that it'd be easy to remove if unused. The only way it wouldn't would be if the closure if complex, but then the cost of 1LEAis unnoticeable.)So personally I think
array::from_fnis right how it is, for all the reasons it ended up this way in the initial PR. And I'd like to see it move forward for stabilization. That's not up to me, though.I don't think
array::try_from_fnis ready yet, though, so I don't know how procedurally libs-api would like to go, here. Usually it FCPs in the tracking issue, but there can only be one FCP per issue/PR, so maybe for a partial one it'd need a separate issue or a stabilization PR in which to make the decision?yoshuawuyts commentedon Dec 1, 2021
Seconding this. I'm trying to collect an iterator into an array, for which I'd like to write:
But because
try_from_fnis hard-coded to return aResult, this does not work. Having anR: Trybound would solve this issue.scottmcm commentedon Dec 1, 2021
@yoshuawuyts I think my PR handles that scenario: https://github.com/rust-lang/rust/pull/91286/files#diff-534d866e6adad8a1f7577c2f1b3eed0b05d5f001c0d5032ac226393736940381R78-R82
scottmcm commentedon Dec 3, 2021
I hate to re-bikeshed, but I stumbled on a possibility which I didn't see mentioned in #75644
I'm making a PR for
array::repeat, to handle simple things like @leonardo-m'srepeat(vec![]). But in doing that I noticed that there's not onlyiter::repeat-- which I was copying forarray::repeat-- but there's alsoiter::repeat_with.So I went to make
array::repeat_with, but of course it's essentially identical to this tracking issue'sarray::from_fn. It's a much better parallel thaniter::from_fn, asiter::repeat_withreturns an "infinite" iterator and thus the closure is just-> Item(notfrom_fn's-> Option<Item>), like how the closure for creating an array is-> Element.So a potential new coat of paint for the constructors could be
array::repeatfor creating by cloning, likerepeat(vec![1]).array::repeat_withfor creating by calling a closure, likerepeat_with(|| Vec::with_capacity(10)).array::try_repeat_withfor creating by a fallible closure.I don't know if this makes me feel differently about the
usizeargument. Allowingrepeat_with(VecDeque::new)does feel somewhat more expected to me thanfrom_fn(VecDeque::new), but I also still agree with the arguments in my previous comment. Of course, having both is also a possibility -- just like there's bothiter::from_fnanditer::repeat_with, despite them being rather similar. Perhaps for nightly it would be reasonable to have both, with notes on their tracking issues to think about the other one if considering for stabilization?c410-f3r commentedon Dec 4, 2021
The two most important things about these functions are (1) Provide an unified way for creating custom arrays (it is common enough for
std) and (2) Take off the user burden of having to deal withunsafe.That said, I will personally support any proposal that will move any function or method towards stabilization as soon as possible. So if desired feel free to create
repeat-like variants, maintain both versions or even close this issue.Although some recent development is happening in this field, sometimes I think that custom array constructors will take, if ever, as long as
try_reserveor more.elichai commentedon Feb 10, 2022
Since I've seen this, I've written
[(); N].map(|_| ...)dozens of times, some required the int and some didn't.So I'd love to see this stabilized :)
Auto merge of rust-lang#94119 - c410-f3r:array-again-and-again, r=sco…
yoshuawuyts commentedon Jul 5, 2022
Now that #94119 has been merged to stabilize this, can we close this issue?
andylizi commentedon Jul 5, 2022
Only
from_fnis stabilized,try_from_fnis still unstable. The latter is blocked on #84277.safinaskar commentedon Jul 17, 2022
Please, also add this functions:
10 remaining items
c410-f3r commentedon Feb 7, 2023
As @scottmcm said, it is necessary to have stable constant closures in order to "constify"
array::from_fnin stable toolchains, which is probably going to happen in the next few years or so. See #106003.I think it is already possible to at least "constify" the hidden underlying machinery but I am not totally sure.
rdrpenguin04 commentedon May 28, 2023
Is there any reason this isn't stable yet?
NathanRoyer commentedon Jul 20, 2023
Hello,
This works, but the documentation doesn't state that the callback parameter will grow upwards, so I'm not confident to use this code.
One day this could end up producing
["lamp", "small", "a", "had", "Mary"], if the implementation decided to "push" values from right to left, with a cb param going from 4 to zero; nothing says otherwise in the doc.Is it possible that one day, we need the callback parameter to go in decreasing order?
If not, I think it would be nice to add a word about this in the documentation.
rdrpenguin04 commentedon May 25, 2024
Are there any open questions about this? If not, could someone start an FCP?
[-]Tracking issue for `array_from_fn` and `try_array_from_fn`[/-][+]Tracking issue for `try_array_from_fn`[/+]c410-f3r commentedon May 25, 2024
try_trait_v2needs to be stabilized first and that probably won't happen in the near future. I am personally betting in 4 years or more (if ever).rdrpenguin04 commentedon May 26, 2024
Why does this depend on try trait necessarily?
try_for_eachis already in the standard library.c410-f3r commentedon May 26, 2024
Well, the original function returned
Resultbut you can see more context about the use ofTryin #90505, #91286 and#94119 (comment).
EDIT: Oh I think it is because of concerns around the
Residualassociated type andtry_for_eachdoesn't use that.scottmcm commentedon May 27, 2024
@c410-f3r is right -- the distinction is the use of the
Residualmechanism, which has no stable use in the library yetSee #94119 (comment) and #94119 (comment)
Same questions as, for example,
Iterator::try_find(#63178).MiSawa commentedon Jun 27, 2025
Noticed that the ascending order is now guaranteed in Rust 1.88 🎉 #139061
bratorange commentedon Jan 29, 2026
When using this feature I got an exception:
EXC_BAD_ACCESS (code=2, address=0x171ae72f0)
The code in question:
pub static FFT_DATA: Lazy<[Mutex<[f32; FREQ_BINS ]>; RMS_BUFFER_SIZE]> =
Lazy::new(|| array::from_fn(|_| {
Mutex::new([0f32; FREQ_BINS])
}));
Environment
OS: macOS 15.6.1
rustc 1.90.0 (1159e78 2025-09-14)
binary: rustc
commit-hash: 1159e78
commit-date: 2025-09-14
host: aarch64-apple-darwin
release: 1.90.0
LLVM version: 20.1.8
rdrpenguin04 commentedon Feb 16, 2026
That looks like it's with the general
from_fnconstructor. Would you be willing to open a separate issue?cargo: Add enum-iterator to prevent 1.2.0 from being used.