Skip to content

Commit 085c4b4

Browse files
committed
Auto merge of #49201 - Phlosioneer:add-trivial-size-hints, r=SimonSapin
Implement some trivial size_hints for various iterators This also implements ExactSizeIterator where applicable. Addresses most of the Iterator traits mentioned in #23708. I intend to do more, but I don't want to make the PR too large.
2 parents 3c5f850 + 5057e3c commit 085c4b4

File tree

13 files changed

+117
-0
lines changed

13 files changed

+117
-0
lines changed

src/libcore/char.rs

+10
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,16 @@ impl<I: Iterator<Item = u8>> Iterator for DecodeUtf8<I> {
902902
}
903903
})
904904
}
905+
906+
#[inline]
907+
fn size_hint(&self) -> (usize, Option<usize>) {
908+
let (lower, upper) = self.0.size_hint();
909+
910+
// A code point is at most 4 bytes long.
911+
let min_code_points = lower / 4;
912+
913+
(min_code_points, upper)
914+
}
905915
}
906916

907917
#[unstable(feature = "decode_utf8", issue = "33906")]

src/libcore/iter/traits.rs

+9
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,15 @@ impl<I, T, E> Iterator for ResultShunt<I, E>
901901
None => None,
902902
}
903903
}
904+
905+
fn size_hint(&self) -> (usize, Option<usize>) {
906+
if self.error.is_some() {
907+
(0, Some(0))
908+
} else {
909+
let (_, upper) = self.iter.size_hint();
910+
(0, upper)
911+
}
912+
}
904913
}
905914

906915
#[stable(feature = "iter_arith_traits_result", since="1.16.0")]

src/libcore/option.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,16 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
11881188
None => None,
11891189
}
11901190
}
1191+
1192+
#[inline]
1193+
fn size_hint(&self) -> (usize, Option<usize>) {
1194+
if self.found_none {
1195+
(0, Some(0))
1196+
} else {
1197+
let (_, upper) = self.iter.size_hint();
1198+
(0, upper)
1199+
}
1200+
}
11911201
}
11921202

11931203
let mut adapter = Adapter { iter: iter.into_iter(), found_none: false };

src/librustc/hir/pat_util.rs

+4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ impl<I> Iterator for EnumerateAndAdjust<I> where I: Iterator {
3131
(if i < self.gap_pos { i } else { i + self.gap_len }, elem)
3232
})
3333
}
34+
35+
fn size_hint(&self) -> (usize, Option<usize>) {
36+
self.enumerate.size_hint()
37+
}
3438
}
3539

3640
pub trait EnumerateAndAdjustIterator {

src/librustc/mir/traversal.rs

+26
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,18 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
7777

7878
None
7979
}
80+
81+
fn size_hint(&self) -> (usize, Option<usize>) {
82+
// All the blocks, minus the number of blocks we've visited.
83+
let remaining = self.mir.basic_blocks().len() - self.visited.count();
84+
85+
// We will visit all remaining blocks exactly once.
86+
(remaining, Some(remaining))
87+
}
8088
}
8189

90+
impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {}
91+
8292
/// Postorder traversal of a graph.
8393
///
8494
/// Postorder traversal is when each node is visited after all of it's
@@ -210,8 +220,18 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
210220

211221
next.map(|(bb, _)| (bb, &self.mir[bb]))
212222
}
223+
224+
fn size_hint(&self) -> (usize, Option<usize>) {
225+
// All the blocks, minus the number of blocks we've visited.
226+
let remaining = self.mir.basic_blocks().len() - self.visited.count();
227+
228+
// We will visit all remaining blocks exactly once.
229+
(remaining, Some(remaining))
230+
}
213231
}
214232

233+
impl<'a, 'tcx> ExactSizeIterator for Postorder<'a, 'tcx> {}
234+
215235
/// Reverse postorder traversal of a graph
216236
///
217237
/// Reverse postorder is the reverse order of a postorder traversal.
@@ -276,4 +296,10 @@ impl<'a, 'tcx> Iterator for ReversePostorder<'a, 'tcx> {
276296

277297
self.blocks.get(self.idx).map(|&bb| (bb, &self.mir[bb]))
278298
}
299+
300+
fn size_hint(&self) -> (usize, Option<usize>) {
301+
(self.idx, Some(self.idx))
302+
}
279303
}
304+
305+
impl<'a, 'tcx> ExactSizeIterator for ReversePostorder<'a, 'tcx> {}

src/librustc/session/search_paths.rs

+7
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,11 @@ impl<'a> Iterator for Iter<'a> {
7878
}
7979
}
8080
}
81+
82+
fn size_hint(&self) -> (usize, Option<usize>) {
83+
// This iterator will never return more elements than the base iterator;
84+
// but it can ignore all the remaining elements.
85+
let (_, upper) = self.iter.size_hint();
86+
(0, upper)
87+
}
8188
}

src/librustc/traits/util.rs

+5
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,11 @@ impl<'tcx,I:Iterator<Item=ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
347347
}
348348
}
349349
}
350+
351+
fn size_hint(&self) -> (usize, Option<usize>) {
352+
let (_, upper) = self.base_iterator.size_hint();
353+
(0, upper)
354+
}
350355
}
351356

352357
///////////////////////////////////////////////////////////////////////////

src/librustc_data_structures/bitvec.rs

+5
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ impl<'a> Iterator for BitVectorIter<'a> {
132132
self.idx += offset + 1;
133133
return Some(self.idx - 1);
134134
}
135+
136+
fn size_hint(&self) -> (usize, Option<usize>) {
137+
let (_, upper) = self.iter.size_hint();
138+
(0, upper)
139+
}
135140
}
136141

137142
impl FromIterator<bool> for BitVector {

src/librustc_data_structures/graph/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,11 @@ impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
334334
self.next = edge.next_edge[self.direction.repr];
335335
Some((edge_index, edge))
336336
}
337+
338+
fn size_hint(&self) -> (usize, Option<usize>) {
339+
// At most, all the edges in the graph.
340+
(0, Some(self.graph.len_edges()))
341+
}
337342
}
338343

339344
pub struct DepthFirstTraversal<'g, N, E>
@@ -383,8 +388,16 @@ impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
383388
}
384389
next
385390
}
391+
392+
fn size_hint(&self) -> (usize, Option<usize>) {
393+
// We will visit every node in the graph exactly once.
394+
let remaining = self.graph.len_nodes() - self.visited.count();
395+
(remaining, Some(remaining))
396+
}
386397
}
387398

399+
impl<'g, N: Debug, E: Debug> ExactSizeIterator for DepthFirstTraversal<'g, N, E> {}
400+
388401
impl<E> Edge<E> {
389402
pub fn source(&self) -> NodeIndex {
390403
self.source

src/librustc_driver/pretty.rs

+7
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,13 @@ impl<'a, 'hir> Iterator for NodesMatchingUII<'a, 'hir> {
584584
&mut NodesMatchingSuffix(ref mut iter) => iter.next(),
585585
}
586586
}
587+
588+
fn size_hint(&self) -> (usize, Option<usize>) {
589+
match self {
590+
&NodesMatchingDirect(ref iter) => iter.size_hint(),
591+
&NodesMatchingSuffix(ref iter) => iter.size_hint(),
592+
}
593+
}
587594
}
588595

589596
impl UserIdentifiedItem {

src/librustc_typeck/check/method/suggest.rs

+7
Original file line numberDiff line numberDiff line change
@@ -730,8 +730,15 @@ impl<'a> Iterator for AllTraits<'a> {
730730
TraitInfo::new(*info)
731731
})
732732
}
733+
734+
fn size_hint(&self) -> (usize, Option<usize>) {
735+
let len = self.borrow.as_ref().unwrap().len() - self.idx;
736+
(len, Some(len))
737+
}
733738
}
734739

740+
impl<'a> ExactSizeIterator for AllTraits<'a> {}
741+
735742

736743
struct UsePlacementFinder<'a, 'tcx: 'a, 'gcx: 'tcx> {
737744
target_module: ast::NodeId,

src/librustdoc/clean/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,11 @@ impl<'a> Iterator for ListAttributesIter<'a> {
604604

605605
None
606606
}
607+
608+
fn size_hint(&self) -> (usize, Option<usize>) {
609+
let lower = self.current_list.len();
610+
(lower, None)
611+
}
607612
}
608613

609614
pub trait AttributesExt {

src/libsyntax_ext/format_foreign.rs

+9
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,11 @@ pub mod printf {
272272
self.s = tail;
273273
Some(sub)
274274
}
275+
276+
fn size_hint(&self) -> (usize, Option<usize>) {
277+
// Substitutions are at least 2 characters long.
278+
(0, Some(self.s.len() / 2))
279+
}
275280
}
276281

277282
enum State {
@@ -782,6 +787,10 @@ pub mod shell {
782787
None => None,
783788
}
784789
}
790+
791+
fn size_hint(&self) -> (usize, Option<usize>) {
792+
(0, Some(self.s.len()))
793+
}
785794
}
786795

787796
/// Parse the next substitution from the input string.

0 commit comments

Comments
 (0)