diff --git a/hercules_ir/src/ir.rs b/hercules_ir/src/ir.rs
index ed340a7604cc2a4bc8c78f1e3743a8343fbb04ea..c4ab9b3ee56a7fc5fbdd4bd1a979f1b921360eb8 100644
--- a/hercules_ir/src/ir.rs
+++ b/hercules_ir/src/ir.rs
@@ -917,11 +917,11 @@ impl Index {
         }
     }
 
-    pub fn lower_case_name(&self) -> &'static str {
+    pub fn lower_case_name(&self) -> String {
         match self {
-            Index::Field(_) => "field",
-            Index::Variant(_) => "variant",
-            Index::Position(_) => "position",
+            Index::Field(idx) => format!("field {}", idx),
+            Index::Variant(idx) => format!("variant {}", idx),
+            Index::Position(idxs) => format!("position {:?}", &*idxs),
         }
     }
 }
diff --git a/hercules_opt/src/editor.rs b/hercules_opt/src/editor.rs
index a75ea38aa3b7703e7efecc952b54d9ccb8df45c6..1981b1297be06a4bf91a59fd870697aeafff4a91 100644
--- a/hercules_opt/src/editor.rs
+++ b/hercules_opt/src/editor.rs
@@ -244,12 +244,12 @@ impl<'a: 'b, 'b> FunctionEditor<'a> {
         self.edits
     }
 
-    pub fn node_ids(&self) -> impl Iterator<Item = NodeID> {
+    pub fn node_ids(&self) -> impl ExactSizeIterator<Item = NodeID> {
         let num = self.function.nodes.len();
         (0..num).map(NodeID::new)
     }
 
-    pub fn dynamic_constant_ids(&self) -> impl Iterator<Item = DynamicConstantID> {
+    pub fn dynamic_constant_ids(&self) -> impl ExactSizeIterator<Item = DynamicConstantID> {
         let num = self.dynamic_constants.borrow().len();
         (0..num).map(DynamicConstantID::new)
     }
@@ -272,6 +272,10 @@ impl<'a, 'b> FunctionEdit<'a, 'b> {
         id.idx() >= self.editor.mutable_nodes.len() || self.editor.mutable_nodes[id.idx()]
     }
 
+    pub fn num_dynamic_constants(&self) -> usize {
+        self.editor.dynamic_constants.borrow().len() + self.added_dynamic_constants.len()
+    }
+
     pub fn add_node(&mut self, node: Node) -> NodeID {
         let id = NodeID::new(self.editor.function.nodes.len() + self.added_nodeids.len());
         // Added nodes need to have an entry in the def-use map.
@@ -312,7 +316,7 @@ impl<'a, 'b> FunctionEdit<'a, 'b> {
         }
     }
 
-    pub fn replace_all_uses(mut self, old: NodeID, new: NodeID) -> Result<Self, Self> {
+    pub fn replace_all_uses(self, old: NodeID, new: NodeID) -> Result<Self, Self> {
         self.replace_all_uses_where(old, new, |_| true)
     }
 
diff --git a/hercules_opt/src/inline.rs b/hercules_opt/src/inline.rs
index 720717b0cdc099e1a5d35516f948f0efcbd2da61..6f6df573bbc6d2cecaad9319eff8ca917244ec41 100644
--- a/hercules_opt/src/inline.rs
+++ b/hercules_opt/src/inline.rs
@@ -200,8 +200,38 @@ fn inline_func(
                     || node.is_dynamic_constant()
                     || node.is_call()
                 {
-                    for (dc_a, dc_b) in zip(dcs_a, dcs_b.iter()) {
-                        substitute_dynamic_constants_in_node(*dc_a, *dc_b, &mut node, &mut edit);
+                    // We have to perform the subsitution in two steps. First,
+                    // we map every dynamic constant A to a non-sense dynamic
+                    // constant ID. Second, we map each non-sense dynamic
+                    // constant ID to the appropriate dynamic constant B. Why
+                    // not just do this in one step from A to B? We update
+                    // dynamic constants one at a time, so imagine the following
+                    // A -> B mappings:
+                    // ID 0 -> ID 1
+                    // ID 1 -> ID 0
+                    // First, we apply the first mapping. This changes all
+                    // references to dynamic constant 0 to dynamic constant 1.
+                    // Then, we apply the second mapping. This updates all
+                    // already present references to dynamic constant 1, as well
+                    // as the new references we just made in the first step. We
+                    // actually want to institute all the updates
+                    // *simultaneously*, hence the two step maneuver.
+                    let num_dcs = edit.num_dynamic_constants();
+                    for (dc_a, dc_n) in zip(dcs_a, num_dcs..) {
+                        substitute_dynamic_constants_in_node(
+                            *dc_a,
+                            DynamicConstantID::new(dc_n),
+                            &mut node,
+                            &mut edit,
+                        );
+                    }
+                    for (dc_n, dc_b) in zip(num_dcs.., dcs_b.iter()) {
+                        substitute_dynamic_constants_in_node(
+                            DynamicConstantID::new(dc_n),
+                            *dc_b,
+                            &mut node,
+                            &mut edit,
+                        );
                     }
                 }
                 let mut uses = get_uses_mut(&mut node);
@@ -267,6 +297,13 @@ fn substitute_dynamic_constants(
         return dc_b;
     }
 
+    // Since we substitute non-sense dynamic constant IDs earlier, we explicitly
+    // check that the provided ID to replace inside of is valid. Otherwise,
+    // ignore.
+    if dc_c.idx() >= edit.num_dynamic_constants() {
+        return dc_c;
+    }
+
     // If C is not just A, look inside of it to possibly substitute a child DC.
     let dc_clone = edit.get_dynamic_constant(dc_c).clone();
     match dc_clone {
@@ -339,7 +376,7 @@ fn substitute_dynamic_constants_in_type(
                 .map(|field_id| substitute_dynamic_constants_in_type(dc_a, dc_b, *field_id, edit))
                 .collect();
             if new_fields != *fields {
-                edit.add_type(Type::Summation(new_fields))
+                edit.add_type(Type::Product(new_fields))
             } else {
                 ty
             }
diff --git a/hercules_opt/src/pass.rs b/hercules_opt/src/pass.rs
index f5e0a9ad5ac9a081efe3016cd0dcb6430c688bc6..33d7bfb3f7d476b262cac094c6b5bfbbebda925e 100644
--- a/hercules_opt/src/pass.rs
+++ b/hercules_opt/src/pass.rs
@@ -788,6 +788,7 @@ impl PassManager {
                         .expect("PANIC: Unable to write output module file contents.");
                 }
             }
+            println!("Ran pass: {:?}", pass);
         }
     }