-
Notifications
You must be signed in to change notification settings - Fork 22
Description
Proposal
Problem statement
It's common to have an Option
containing an iterator, or something that can be transformed into an iterator, and wanting to get an iterator out of it. This can be done with option.into_iter().flat_map(|it| it.iter())
. The verbosity is okay (although not great, and this isn't easily discoverable), but this is not as efficient as it can be, because FlatMap
/Flatten
need to handle iteration for generic iterators, which can be a lot slower. Internal iteration is often fine (the FlatMap
can be optimized) but external iteration uses way more instructions than needed. As an example, see this godbolt link, which contains way more instructions than needed.
Code for the godbolt link:
unsafe extern "C" {
safe fn black_box(v: &i32);
}
#[unsafe(no_mangle)]
pub fn foo(v: Option<&[i32]>) {
for i in v.into_iter().flatten() {
black_box(i)
}
}
In addition, FlatMap
/Flatten
can't provide an accurate size_hint()
/TrustedLen
, which can make collecting even slower.
Motivating examples or use cases
The rust-analyzer codebase contain dozens (more than 20) instances of the abovementioned pattern.
Solution sketch
Include a method in Option
, that takes a callback that returns an iterator and returns an iterator for that behaves like FlatMap
but is specialized for Option
.
I chose to call this method map_iter()
, but I'm not really pleased with this name, I just don't have a better one. So I'll be happy to hear other opinions.
Alternatives
At least the size_hint()
part is fixable I believe with specialization. The next()
part is harder, it may not be possible to specialize it to the most efficient codegen.
There's also the argument that adding a method purely for the sake of optimization isn't a good idea. While I do think a special method is also more easily discoverable and nicer to type, the main motivation is indeed perf. But I do think if we can't get this level of perf from alternatives it's worth adding the method, even for perf sake only.
What happens now?
This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.
Possible responses
The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):
- We think this problem seems worth solving, and the standard library might be the right place to solve it.
- We think that this probably doesn't belong in the standard library.
Second, if there's a concrete solution:
- We think this specific solution looks roughly right, approved, you or someone else should implement this. (Further review will still happen on the subsequent implementation PR.)
- We're not sure this is the right solution, and the alternatives or other materials don't give us enough information to be sure about that. Here are some questions we have that aren't answered, or rough ideas about alternatives we'd want to see discussed.