From 5c3e5af2ed3776755e584530fd8915544292b821 Mon Sep 17 00:00:00 2001
From: Scott McMurray <scottmcm@users.noreply.github.com>
Date: Mon, 3 Apr 2023 14:22:09 -0700
Subject: [PATCH] Doc-comment  `IndexVec::from_elem` and use it in a few more
 places

---
 .../src/type_check/liveness/local_use_map.rs          |  4 ++--
 compiler/rustc_index/src/vec.rs                       | 11 +++++++++++
 .../src/infer/lexical_region_resolve/mod.rs           |  2 +-
 compiler/rustc_mir_transform/src/coverage/graph.rs    |  5 ++---
 compiler/rustc_ty_utils/src/layout.rs                 |  2 +-
 5 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
index 8023ef60d20..2c387edfef0 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
@@ -63,7 +63,7 @@ impl LocalUseMap {
         elements: &RegionValueElements,
         body: &Body<'_>,
     ) -> Self {
-        let nones = IndexVec::from_elem_n(None, body.local_decls.len());
+        let nones = IndexVec::from_elem(None, &body.local_decls);
         let mut local_use_map = LocalUseMap {
             first_def_at: nones.clone(),
             first_use_at: nones.clone(),
@@ -76,7 +76,7 @@ impl LocalUseMap {
         }
 
         let mut locals_with_use_data: IndexVec<Local, bool> =
-            IndexVec::from_elem_n(false, body.local_decls.len());
+            IndexVec::from_elem(false, &body.local_decls);
         live_locals.iter().for_each(|&local| locals_with_use_data[local] = true);
 
         LocalUseMapBuild { local_use_map: &mut local_use_map, elements, locals_with_use_data }
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index 5945de2302a..16cf9ae5cfc 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -129,6 +129,17 @@ impl<I: Idx, T> IndexVec<I, T> {
         IndexVec { raw: Vec::with_capacity(capacity), _marker: PhantomData }
     }
 
+    /// Creates a new vector with a copy of `elem` for each index in `universe`.
+    ///
+    /// Thus `IndexVec::from_elem(elem, &universe)` is equivalent to
+    /// `IndexVec::<I, _>::from_elem_n(elem, universe.len())`. That can help
+    /// type inference as it ensures that the resulting vector uses the same
+    /// index type as `universe`, rather than something potentially surprising.
+    ///
+    /// For example, if you want to store data for each local in a MIR body,
+    /// using `let mut uses = IndexVec::from_elem(vec![], &body.local_decls);`
+    /// ensures that `uses` is an `IndexVec<Local, _>`, and thus can give
+    /// better error messages later if one accidentally mismatches indices.
     #[inline]
     pub fn from_elem<S>(elem: T, universe: &IndexSlice<I, S>) -> Self
     where
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index 9e2bdb7f510..f298b95ca35 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -203,7 +203,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
 
         // Tracks the `VarSubVar` constraints generated for each region vid. We
         // later use this to expand across vids.
-        let mut constraints = IndexVec::from_elem_n(Vec::new(), var_values.values.len());
+        let mut constraints = IndexVec::from_elem(Vec::new(), &var_values.values);
         // Tracks the changed region vids.
         let mut changes = Vec::new();
         for constraint in self.data.constraints.keys() {
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 689d6c71361..6a73f2a6578 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -37,8 +37,7 @@ impl CoverageGraph {
         // `SwitchInt` to have multiple targets to the same destination `BasicBlock`, so
         // de-duplication is required. This is done without reordering the successors.
 
-        let bcbs_len = bcbs.len();
-        let mut seen = IndexVec::from_elem_n(false, bcbs_len);
+        let mut seen = IndexVec::from_elem(false, &bcbs);
         let successors = IndexVec::from_fn_n(
             |bcb| {
                 for b in seen.iter_mut() {
@@ -60,7 +59,7 @@ impl CoverageGraph {
             bcbs.len(),
         );
 
-        let mut predecessors = IndexVec::from_elem_n(Vec::new(), bcbs.len());
+        let mut predecessors = IndexVec::from_elem(Vec::new(), &bcbs);
         for (bcb, bcb_successors) in successors.iter_enumerated() {
             for &successor in bcb_successors {
                 predecessors[successor].push(bcb);
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 73f86f74d14..e8155520c9b 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -522,7 +522,7 @@ fn generator_saved_local_eligibility(
     use SavedLocalEligibility::*;
 
     let mut assignments: IndexVec<GeneratorSavedLocal, SavedLocalEligibility> =
-        IndexVec::from_elem_n(Unassigned, info.field_tys.len());
+        IndexVec::from_elem(Unassigned, &info.field_tys);
 
     // The saved locals not eligible for overlap. These will get
     // "promoted" to the prefix of our generator.