From d97379a96e594820b9e865ae56cb8d753bf6b06a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Kuras?= <bartlomiej.kuras@o2.pl>
Date: Sat, 7 Dec 2019 19:37:09 +0100
Subject: [PATCH] Added ExactSizeIterator bound to return types in librustc in
 several places

---
 src/bootstrap/lib.rs                               |  2 +-
 src/librustc/infer/canonical/query_response.rs     |  2 +-
 src/librustc/infer/outlives/free_region_map.rs     |  2 +-
 src/librustc/mir/mod.rs                            | 14 +++++++++-----
 .../traits/specialize/specialization_graph.rs      |  4 +++-
 src/librustc/ty/mod.rs                             | 12 ++++++++++--
 src/librustc/ty/sty.rs                             | 12 +++++++-----
 .../graph/implementation/mod.rs                    |  8 ++++++--
 .../transitive_relation.rs                         |  2 +-
 src/librustc_incremental/persist/dirty_clean.rs    |  2 +-
 src/librustc_index/bit_set.rs                      |  4 ++--
 src/librustc_index/vec.rs                          | 10 ++++++----
 src/librustc_mir/borrow_check/location.rs          |  2 +-
 .../borrow_check/nll/member_constraints.rs         |  2 +-
 .../borrow_check/nll/region_infer/mod.rs           |  2 +-
 .../borrow_check/nll/region_infer/values.rs        |  2 +-
 .../borrow_check/nll/universal_regions.rs          |  8 +++++---
 src/librustc_mir/hair/pattern/_match.rs            |  2 +-
 src/librustc_target/abi/mod.rs                     |  4 +++-
 19 files changed, 61 insertions(+), 35 deletions(-)

diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 39d7ea922bced..db955052cab77 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -1274,7 +1274,7 @@ impl Build {
         t!(fs::remove_dir_all(dir))
     }
 
-    fn read_dir(&self, dir: &Path) -> impl Iterator<Item=fs::DirEntry> {
+    fn read_dir(&self, dir: &Path) -> impl Iterator<Item=fs::DirEntry> + ExactSizeIterator {
         let iter = match fs::read_dir(dir) {
             Ok(v) => v,
             Err(_) if self.config.dry_run => return vec![].into_iter(),
diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs
index 825e98cedb9e0..d9025bfe620e0 100644
--- a/src/librustc/infer/canonical/query_response.rs
+++ b/src/librustc/infer/canonical/query_response.rs
@@ -574,7 +574,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         unsubstituted_region_constraints: &'a [QueryOutlivesConstraint<'tcx>],
         result_subst: &'a CanonicalVarValues<'tcx>,
-    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'tcx> {
+    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + ExactSizeIterator + 'a + Captures<'tcx> {
         unsubstituted_region_constraints
             .iter()
             .map(move |constraint| {
diff --git a/src/librustc/infer/outlives/free_region_map.rs b/src/librustc/infer/outlives/free_region_map.rs
index fd8ccce683352..d88cce0e18e18 100644
--- a/src/librustc/infer/outlives/free_region_map.rs
+++ b/src/librustc/infer/outlives/free_region_map.rs
@@ -11,7 +11,7 @@ pub struct FreeRegionMap<'tcx> {
 }
 
 impl<'tcx> FreeRegionMap<'tcx> {
-    pub fn elements(&self) -> impl Iterator<Item=&Region<'tcx>> {
+    pub fn elements(&self) -> impl Iterator<Item=&Region<'tcx>> + ExactSizeIterator {
         self.relation.elements()
     }
 
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index df5d4997e089a..0a6bdbf8b85ed 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -282,15 +282,15 @@ impl<'tcx> Body<'tcx> {
 
     /// Returns an iterator over all function arguments.
     #[inline]
-    pub fn args_iter(&self) -> impl Iterator<Item = Local> {
+    pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
         let arg_count = self.arg_count;
-        (1..=arg_count).map(Local::new)
+        (1..arg_count+1).map(Local::new)
     }
 
     /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
     /// locals that are neither arguments nor the return place).
     #[inline]
-    pub fn vars_and_temps_iter(&self) -> impl Iterator<Item = Local> {
+    pub fn vars_and_temps_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
         let arg_count = self.arg_count;
         let local_count = self.local_decls.len();
         (arg_count + 1..local_count).map(Local::new)
@@ -2384,11 +2384,15 @@ impl<'tcx> UserTypeProjections {
         UserTypeProjections { contents: projs.collect() }
     }
 
-    pub fn projections_and_spans(&self) -> impl Iterator<Item = &(UserTypeProjection, Span)> {
+    pub fn projections_and_spans(&self)
+        -> impl Iterator<Item = &(UserTypeProjection, Span)> + ExactSizeIterator
+    {
         self.contents.iter()
     }
 
-    pub fn projections(&self) -> impl Iterator<Item = &UserTypeProjection> {
+    pub fn projections(&self)
+        -> impl Iterator<Item = &UserTypeProjection> + ExactSizeIterator
+    {
         self.contents.iter().map(|&(ref user_type, _span)| user_type)
     }
 
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index b8ddf6078bda6..476dac07cf452 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -414,7 +414,9 @@ impl<'tcx> Node {
     }
 
     /// Iterate over the items defined directly by the given (impl or trait) node.
-    pub fn items(&self, tcx: TyCtxt<'tcx>) -> ty::AssocItemsIterator<'tcx> {
+    pub fn items(&self, tcx: TyCtxt<'tcx>)
+        -> impl Iterator<Item = ty::AssocItem> + ExactSizeIterator + Clone + 'tcx
+    {
         tcx.associated_items(self.def_id())
     }
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index c9a934e9ebd84..ff84486c2f8e7 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2376,7 +2376,7 @@ impl<'tcx> AdtDef {
     pub fn discriminants(
         &'tcx self,
         tcx: TyCtxt<'tcx>,
-    ) -> impl Iterator<Item = (VariantIdx, Discr<'tcx>)> + Captures<'tcx> {
+    ) -> impl Iterator<Item = (VariantIdx, Discr<'tcx>)> + ExactSizeIterator + Captures<'tcx> {
         let repr_type = self.repr.discr_type();
         let initial = repr_type.initial_discriminant(tcx);
         let mut prev_discr = None::<Discr<'tcx>>;
@@ -2740,7 +2740,9 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Returns an iterator of the `DefId`s for all body-owners in this
     /// crate. If you would prefer to iterate over the bodies
     /// themselves, you can do `self.hir().krate().body_ids.iter()`.
-    pub fn body_owners(self) -> impl Iterator<Item = DefId> + Captures<'tcx> + 'tcx {
+    pub fn body_owners(self)
+        -> impl Iterator<Item = DefId> + ExactSizeIterator + Captures<'tcx> + 'tcx
+    {
         self.hir().krate()
                   .body_ids
                   .iter()
@@ -3116,6 +3118,12 @@ impl Iterator for AssocItemsIterator<'_> {
     }
 }
 
+impl ExactSizeIterator for AssocItemsIterator<'_> {
+    fn len(&self) -> usize {
+        self.def_ids.len() - self.next_index
+    }
+}
+
 fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> AssocItem {
     let id = tcx.hir().as_local_hir_id(def_id).unwrap();
     let parent_id = tcx.hir().get_parent_item(id);
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 6cb0d1e9946b5..70236ee2dbc63 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -345,7 +345,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
         self,
         def_id: DefId,
         tcx: TyCtxt<'_>,
-    ) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
+    ) -> impl Iterator<Item = Ty<'tcx>> + ExactSizeIterator + 'tcx {
         let SplitClosureSubsts { upvar_kinds, .. } = self.split(def_id, tcx);
         upvar_kinds.iter().map(|t| {
             if let GenericArgKind::Type(ty) = t.unpack() {
@@ -433,7 +433,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
         self,
         def_id: DefId,
         tcx: TyCtxt<'_>,
-    ) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
+    ) -> impl Iterator<Item = Ty<'tcx>> + ExactSizeIterator + 'tcx {
         let SplitGeneratorSubsts { upvar_kinds, .. } = self.split(def_id, tcx);
         upvar_kinds.iter().map(|t| {
             if let GenericArgKind::Type(ty) = t.unpack() {
@@ -551,7 +551,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
         self,
         def_id: DefId,
         tcx: TyCtxt<'tcx>,
-    ) -> impl Iterator<Item = impl Iterator<Item = Ty<'tcx>> + Captures<'tcx>> {
+    ) -> impl Iterator<Item = impl Iterator<Item = Ty<'tcx>> + ExactSizeIterator + Captures<'tcx>> {
         let layout = tcx.generator_layout(def_id);
         layout.variant_fields.iter().map(move |variant| {
             variant.iter().map(move |field| {
@@ -563,7 +563,9 @@ impl<'tcx> GeneratorSubsts<'tcx> {
     /// This is the types of the fields of a generator which are not stored in a
     /// variant.
     #[inline]
-    pub fn prefix_tys(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = Ty<'tcx>> {
+    pub fn prefix_tys(self, def_id: DefId, tcx: TyCtxt<'tcx>)
+        -> impl Iterator<Item = Ty<'tcx>> + ExactSizeIterator
+    {
         self.upvar_tys(def_id, tcx)
     }
 }
@@ -580,7 +582,7 @@ impl<'tcx> UpvarSubsts<'tcx> {
         self,
         def_id: DefId,
         tcx: TyCtxt<'tcx>,
-    ) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
+    ) -> impl Iterator<Item = Ty<'tcx>> + ExactSizeIterator + 'tcx {
         let upvar_kinds = match self {
             UpvarSubsts::Closure(substs) => substs.as_closure().split(def_id, tcx).upvar_kinds,
             UpvarSubsts::Generator(substs) => substs.as_generator().split(def_id, tcx).upvar_kinds,
diff --git a/src/librustc_data_structures/graph/implementation/mod.rs b/src/librustc_data_structures/graph/implementation/mod.rs
index 9fdcea6df88c5..2a341c594f1c2 100644
--- a/src/librustc_data_structures/graph/implementation/mod.rs
+++ b/src/librustc_data_structures/graph/implementation/mod.rs
@@ -186,14 +186,18 @@ impl<N: Debug, E: Debug> Graph<N, E> {
 
     // # Iterating over nodes, edges
 
-    pub fn enumerated_nodes(&self) -> impl Iterator<Item = (NodeIndex, &Node<N>)> {
+    pub fn enumerated_nodes(&self)
+        -> impl Iterator<Item = (NodeIndex, &Node<N>)> + ExactSizeIterator
+    {
         self.nodes
             .iter()
             .enumerate()
             .map(|(idx, n)| (NodeIndex(idx), n))
     }
 
-    pub fn enumerated_edges(&self) -> impl Iterator<Item = (EdgeIndex, &Edge<E>)> {
+    pub fn enumerated_edges(&self)
+        -> impl Iterator<Item = (EdgeIndex, &Edge<E>)> + ExactSizeIterator
+    {
         self.edges
             .iter()
             .enumerate()
diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs
index a3926c1555172..8210dc6cb0b00 100644
--- a/src/librustc_data_structures/transitive_relation.rs
+++ b/src/librustc_data_structures/transitive_relation.rs
@@ -60,7 +60,7 @@ impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
         self.edges.is_empty()
     }
 
-    pub fn elements(&self) -> impl Iterator<Item=&T> {
+    pub fn elements(&self) -> impl Iterator<Item=&T> + ExactSizeIterator {
         self.elements.iter()
     }
 
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index ea156a94ea17b..4619277a5dae4 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -449,7 +449,7 @@ impl DirtyCleanVisitor<'tcx> {
         &self,
         labels: &'l Labels,
         def_id: DefId
-    ) -> impl Iterator<Item = DepNode> + 'l {
+    ) -> impl Iterator<Item = DepNode> + ExactSizeIterator + 'l {
         let def_path_hash = self.tcx.def_path_hash(def_id);
         labels
             .iter()
diff --git a/src/librustc_index/bit_set.rs b/src/librustc_index/bit_set.rs
index 9ed5ef5a539a1..cc56aa2701f82 100644
--- a/src/librustc_index/bit_set.rs
+++ b/src/librustc_index/bit_set.rs
@@ -748,7 +748,7 @@ impl<R: Idx, C: Idx> BitMatrix<R, C> {
         }
     }
 
-    pub fn rows(&self) -> impl Iterator<Item = R> {
+    pub fn rows(&self) -> impl Iterator<Item = R> + ExactSizeIterator {
         (0..self.num_rows).map(R::new)
     }
 
@@ -975,7 +975,7 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
         self.ensure_row(row).insert_all();
     }
 
-    pub fn rows(&self) -> impl Iterator<Item = R> {
+    pub fn rows(&self) -> impl Iterator<Item = R> + ExactSizeIterator {
         self.rows.indices()
     }
 
diff --git a/src/librustc_index/vec.rs b/src/librustc_index/vec.rs
index 6e80b48a68560..84b460bf5717e 100644
--- a/src/librustc_index/vec.rs
+++ b/src/librustc_index/vec.rs
@@ -633,14 +633,16 @@ impl<I: Idx, T> IndexVec<I, T> {
     }
 
     #[inline]
-    pub fn drain<'a, R: RangeBounds<usize>>(
-        &'a mut self, range: R) -> impl Iterator<Item=T> + 'a {
+    pub fn drain<'a, R: RangeBounds<usize>>(&'a mut self, range: R)
+        -> impl Iterator<Item=T> + ExactSizeIterator + 'a
+    {
         self.raw.drain(range)
     }
 
     #[inline]
-    pub fn drain_enumerated<'a, R: RangeBounds<usize>>(
-        &'a mut self, range: R) -> impl Iterator<Item=(I, T)> + 'a {
+    pub fn drain_enumerated<'a, R: RangeBounds<usize>>(&'a mut self, range: R)
+        -> impl Iterator<Item=(I, T)> + ExactSizeIterator + 'a
+    {
         self.raw.drain(range).enumerate().map(IntoIdx { _marker: PhantomData })
     }
 
diff --git a/src/librustc_mir/borrow_check/location.rs b/src/librustc_mir/borrow_check/location.rs
index 9e94317b87e54..6a24b1a1df442 100644
--- a/src/librustc_mir/borrow_check/location.rs
+++ b/src/librustc_mir/borrow_check/location.rs
@@ -53,7 +53,7 @@ impl LocationTable {
         }
     }
 
-    crate fn all_points(&self) -> impl Iterator<Item = LocationIndex> {
+    crate fn all_points(&self) -> impl Iterator<Item = LocationIndex> + ExactSizeIterator {
         (0..self.num_points).map(LocationIndex::new)
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/member_constraints.rs b/src/librustc_mir/borrow_check/nll/member_constraints.rs
index 75213d30982f9..5b014ec85284b 100644
--- a/src/librustc_mir/borrow_check/nll/member_constraints.rs
+++ b/src/librustc_mir/borrow_check/nll/member_constraints.rs
@@ -155,7 +155,7 @@ where
 {
     crate fn all_indices(
         &self,
-    ) -> impl Iterator<Item = NllMemberConstraintIndex> {
+    ) -> impl Iterator<Item = NllMemberConstraintIndex> + ExactSizeIterator {
         self.constraints.indices()
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index 85031d6210a4d..b488875ee0914 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -422,7 +422,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     }
 
     /// Returns an iterator over all the region indices.
-    pub fn regions(&self) -> impl Iterator<Item = RegionVid> {
+    pub fn regions(&self) -> impl Iterator<Item = RegionVid> + ExactSizeIterator {
         self.definitions.indices()
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
index b4414c514c532..868ddc0c1faf3 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
@@ -162,7 +162,7 @@ impl<N: Idx> LivenessValues<N> {
     }
 
     /// Iterate through each region that has a value in this set.
-    crate fn rows(&self) -> impl Iterator<Item=N> {
+    crate fn rows(&self) -> impl Iterator<Item=N> + ExactSizeIterator {
         self.points.rows()
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index 9ad15fca0017d..51a7cb054b6e9 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -107,7 +107,9 @@ impl<'tcx> DefiningTy<'tcx> {
     /// not a closure or generator, there are no upvars, and hence it
     /// will be an empty list. The order of types in this list will
     /// match up with the upvar order in the HIR, typesystem, and MIR.
-    pub fn upvar_tys(self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
+    pub fn upvar_tys(self, tcx: TyCtxt<'tcx>)
+        -> impl Iterator<Item = Ty<'tcx>> + ExactSizeIterator + 'tcx
+    {
         match self {
             DefiningTy::Closure(def_id, substs) => Either::Left(
                 substs.as_closure().upvar_tys(def_id, tcx)
@@ -267,7 +269,7 @@ impl<'tcx> UniversalRegions<'tcx> {
 
     /// Returns an iterator over all the RegionVids corresponding to
     /// universally quantified free regions.
-    pub fn universal_regions(&self) -> impl Iterator<Item = RegionVid> {
+    pub fn universal_regions(&self) -> impl Iterator<Item = RegionVid> + ExactSizeIterator {
         (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::new)
     }
 
@@ -293,7 +295,7 @@ impl<'tcx> UniversalRegions<'tcx> {
     /// Gets an iterator over all the early-bound regions that have names.
     pub fn named_universal_regions<'s>(
         &'s self,
-    ) -> impl Iterator<Item = (ty::Region<'tcx>, ty::RegionVid)> + 's {
+    ) -> impl Iterator<Item = (ty::Region<'tcx>, ty::RegionVid)> + ExactSizeIterator + 's {
         self.indices.indices.iter().map(|(&r, &v)| (r, v))
     }
 
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 37a9381271a8c..45c19812e463b 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -396,7 +396,7 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
         PatStack::from_slice(&self.0[1..])
     }
 
-    fn iter(&self) -> impl Iterator<Item = &Pat<'tcx>> {
+    fn iter(&self) -> impl Iterator<Item = &Pat<'tcx>> + ExactSizeIterator {
         self.0.iter().map(|p| *p)
     }
 
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index ac781819cc35e..3876c6e4132a2 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -723,7 +723,9 @@ impl FieldPlacement {
 
     /// Gets source indices of the fields by increasing offsets.
     #[inline]
-    pub fn index_by_increasing_offset<'a>(&'a self) -> impl Iterator<Item=usize>+'a {
+    pub fn index_by_increasing_offset<'a>(&'a self)
+        -> impl Iterator<Item=usize> + ExactSizeIterator + 'a
+    {
         let mut inverse_small = [0u8; 64];
         let mut inverse_big = vec![];
         let use_small = self.count() <= inverse_small.len();