From 619003d1d414167630331efffe83702f74413be6 Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Tue, 20 Mar 2018 05:33:59 -0400 Subject: [PATCH 1/5] Implement some trivial size_hints for various iterators This also implements ExactSizeIterator where applicable. Addresses most of the Iterator traits mentioned in #23708. --- src/libcore/char.rs | 5 ++++ src/libcore/iter/traits.rs | 4 ++++ src/libcore/option.rs | 5 ++++ src/librustc/hir/pat_util.rs | 4 ++++ src/librustc/mir/traversal.rs | 26 +++++++++++++++++++++ src/librustc/session/search_paths.rs | 7 ++++++ src/librustc/traits/util.rs | 5 ++++ src/librustc_data_structures/bitvec.rs | 5 ++++ src/librustc_data_structures/graph/mod.rs | 13 +++++++++++ src/librustc_driver/pretty.rs | 7 ++++++ src/librustc_typeck/check/method/suggest.rs | 7 ++++++ src/librustdoc/clean/mod.rs | 5 ++++ src/libsyntax_ext/format_foreign.rs | 9 +++++++ 13 files changed, 102 insertions(+) diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 1638f9710f597..2f56238a4638b 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -902,6 +902,11 @@ impl> Iterator for DecodeUtf8 { } }) } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } } #[unstable(feature = "decode_utf8", issue = "33906")] diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 0267fcd375453..5e4622f804aff 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -901,6 +901,10 @@ impl Iterator for ResultShunt None => None, } } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } } #[stable(feature = "iter_arith_traits_result", since="1.16.0")] diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 570f745f8330c..1ca69f3f503d1 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1188,6 +1188,11 @@ impl> FromIterator> for Option { None => None, } } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } } let mut adapter = Adapter { iter: iter.into_iter(), found_none: false }; diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index 2bec224362ea6..1f00a3ab1f5de 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -31,6 +31,10 @@ impl Iterator for EnumerateAndAdjust where I: Iterator { (if i < self.gap_pos { i } else { i + self.gap_len }, elem) }) } + + fn size_hint(&self) -> (usize, Option) { + self.enumerate.size_hint() + } } pub trait EnumerateAndAdjustIterator { diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index 74c3408c4c2f6..666ca5eabe81b 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -77,8 +77,18 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { None } + + fn size_hint(&self) -> (usize, Option) { + // All the blocks, minus the number of blocks we've visited. + let remaining = self.mir.basic_blocks().len() - self.visited.count(); + + // We will visit all remaining blocks exactly once. + (remaining, Some(remaining)) + } } +impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {} + /// Postorder traversal of a graph. /// /// 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> { next.map(|(bb, _)| (bb, &self.mir[bb])) } + + fn size_hint(&self) -> (usize, Option) { + // All the blocks, minus the number of blocks we've visited. + let remaining = self.mir.basic_blocks().len() - self.visited.count(); + + // We will visit all remaining blocks exactly once. + (remaining, Some(remaining)) + } } +impl<'a, 'tcx> ExactSizeIterator for Postorder<'a, 'tcx> {} + /// Reverse postorder traversal of a graph /// /// Reverse postorder is the reverse order of a postorder traversal. @@ -276,4 +296,10 @@ impl<'a, 'tcx> Iterator for ReversePostorder<'a, 'tcx> { self.blocks.get(self.idx).map(|&bb| (bb, &self.mir[bb])) } + + fn size_hint(&self) -> (usize, Option) { + (self.idx, Some(self.idx)) + } } + +impl<'a, 'tcx> ExactSizeIterator for ReversePostorder<'a, 'tcx> {} diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs index 5bbc6841693ea..d2dca9f60845a 100644 --- a/src/librustc/session/search_paths.rs +++ b/src/librustc/session/search_paths.rs @@ -78,4 +78,11 @@ impl<'a> Iterator for Iter<'a> { } } } + + fn size_hint(&self) -> (usize, Option) { + // This iterator will never return more elements than the base iterator; + // but it can ignore all the remaining elements. + let (_, upper) = self.iter.size_hint(); + (0, upper) + } } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 8f7a24057472c..9e38911f53c9a 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -347,6 +347,11 @@ impl<'tcx,I:Iterator>> Iterator for FilterToTraits { } } } + + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.base_iterator.size_hint(); + (0, upper) + } } /////////////////////////////////////////////////////////////////////////// diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs index 54565afa4c6c7..28e3180063c17 100644 --- a/src/librustc_data_structures/bitvec.rs +++ b/src/librustc_data_structures/bitvec.rs @@ -132,6 +132,11 @@ impl<'a> Iterator for BitVectorIter<'a> { self.idx += offset + 1; return Some(self.idx - 1); } + + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } } impl FromIterator for BitVector { diff --git a/src/librustc_data_structures/graph/mod.rs b/src/librustc_data_structures/graph/mod.rs index 1945b82c03145..e2b393071ff5c 100644 --- a/src/librustc_data_structures/graph/mod.rs +++ b/src/librustc_data_structures/graph/mod.rs @@ -334,6 +334,11 @@ impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> { self.next = edge.next_edge[self.direction.repr]; Some((edge_index, edge)) } + + fn size_hint(&self) -> (usize, Option) { + // At most, all the edges in the graph. + (0, Some(self.graph.len_edges())) + } } pub struct DepthFirstTraversal<'g, N, E> @@ -383,8 +388,16 @@ impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> { } next } + + fn size_hint(&self) -> (usize, Option) { + // We will visit every node in the graph exactly once. + let remaining = self.graph.len_nodes() - self.visited.count(); + (remaining, Some(remaining)) + } } +impl<'g, N: Debug, E: Debug> ExactSizeIterator for DepthFirstTraversal<'g, N, E> {} + impl Edge { pub fn source(&self) -> NodeIndex { self.source diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 4ae6a93d6983a..c5e7fdb30d36a 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -584,6 +584,13 @@ impl<'a, 'hir> Iterator for NodesMatchingUII<'a, 'hir> { &mut NodesMatchingSuffix(ref mut iter) => iter.next(), } } + + fn size_hint(&self) -> (usize, Option) { + match self { + &NodesMatchingDirect(ref iter) => iter.size_hint(), + &NodesMatchingSuffix(ref iter) => iter.size_hint(), + } + } } impl UserIdentifiedItem { diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 61afac97d6409..a753698050332 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -718,8 +718,15 @@ impl<'a> Iterator for AllTraits<'a> { TraitInfo::new(*info) }) } + + fn size_hint(&self) -> (usize, Option) { + let len = self.borrow.as_ref().unwrap().len() - self.idx; + (len, Some(len)) + } } +impl<'a> ExactSizeIterator for AllTraits<'a> {} + struct UsePlacementFinder<'a, 'tcx: 'a, 'gcx: 'tcx> { target_module: ast::NodeId, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 904c24815cb7f..a2a0e878fd888 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -602,6 +602,11 @@ impl<'a> Iterator for ListAttributesIter<'a> { None } + + fn size_hint(&self) -> (usize, Option) { + let lower = self.current_list.len(); + (lower, None) + } } pub trait AttributesExt { diff --git a/src/libsyntax_ext/format_foreign.rs b/src/libsyntax_ext/format_foreign.rs index 0476d7d4fcc1c..e95c6f2e1243f 100644 --- a/src/libsyntax_ext/format_foreign.rs +++ b/src/libsyntax_ext/format_foreign.rs @@ -272,6 +272,11 @@ pub mod printf { self.s = tail; Some(sub) } + + fn size_hint(&self) -> (usize, Option) { + // Substitutions are at least 2 characters long. + (0, Some(self.s.len() / 2)) + } } enum State { @@ -782,6 +787,10 @@ pub mod shell { None => None, } } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.s.len())) + } } /// Parse the next substitution from the input string. From 8334977dcffbd538fbd1457555ea3d80cc5eb64b Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Sat, 24 Mar 2018 23:35:16 -0400 Subject: [PATCH 2/5] Fix incorrect lower bounds --- src/libcore/char.rs | 7 ++++++- src/libcore/iter/traits.rs | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 2f56238a4638b..4420eff06ed22 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -905,7 +905,12 @@ impl> Iterator for DecodeUtf8 { #[inline] fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() + let len = self.iter.len(); + + // A code point is at most 4 bytes long. + let min_code_points = len / 4; + + (min_code_points, Some(len)) } } diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 5e4622f804aff..c3aebc4fb23ce 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -903,7 +903,12 @@ impl Iterator for ResultShunt } fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + if self.error.is_some() { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } } } From a907d9aad20a728e02897f660995b07646658a44 Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Sat, 24 Mar 2018 23:45:20 -0400 Subject: [PATCH 3/5] Fix syntax error --- src/libcore/char.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 4420eff06ed22..b8d1f91c24795 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -905,7 +905,7 @@ impl> Iterator for DecodeUtf8 { #[inline] fn size_hint(&self) -> (usize, Option) { - let len = self.iter.len(); + let len = self.0.len(); // A code point is at most 4 bytes long. let min_code_points = len / 4; From 01af316867dd6477072e0feae2d7cead2229ebfd Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Sun, 25 Mar 2018 00:00:18 -0400 Subject: [PATCH 4/5] Fix incorrect copy-pasted code It's late. --- src/libcore/char.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcore/char.rs b/src/libcore/char.rs index b8d1f91c24795..c74b23da39cfc 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -905,12 +905,12 @@ impl> Iterator for DecodeUtf8 { #[inline] fn size_hint(&self) -> (usize, Option) { - let len = self.0.len(); + let (lower, upper) = self.0.size_hint(); // A code point is at most 4 bytes long. - let min_code_points = len / 4; + let min_code_points = lower / 4; - (min_code_points, Some(len)) + (min_code_points, upper) } } From 5057e3c9e10f329d39a0e45607cf6a9ab467f7bf Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Sat, 31 Mar 2018 01:13:02 -0400 Subject: [PATCH 5/5] Commit code for option size hint --- src/libcore/option.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 1ca69f3f503d1..61ef6798b2efb 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1191,7 +1191,12 @@ impl> FromIterator> for Option { #[inline] fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + if self.found_none { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } } }