about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTomasz Miąsko <tomasz.miasko@gmail.com>2025-04-30 13:02:30 +0200
committerTomasz Miąsko <tomasz.miasko@gmail.com>2025-04-30 14:35:23 +0200
commitb9e0ecdd7626e76f0b72ada922e5c07eae75cdf5 (patch)
treec1e488c03f12ccfec5b50e77c6fa2b25e690534e
parent88a86794b9e5bcda28b8f89e6b6264bb7bc042c4 (diff)
downloadrust-b9e0ecdd7626e76f0b72ada922e5c07eae75cdf5.tar.gz
rust-b9e0ecdd7626e76f0b72ada922e5c07eae75cdf5.zip
transmutability: merge contiguous runs with a common destination
-rw-r--r--compiler/rustc_transmute/src/layout/dfa.rs24
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/tests.rs2
2 files changed, 19 insertions, 7 deletions
diff --git a/compiler/rustc_transmute/src/layout/dfa.rs b/compiler/rustc_transmute/src/layout/dfa.rs
index 05afa28db31..6d072c336af 100644
--- a/compiler/rustc_transmute/src/layout/dfa.rs
+++ b/compiler/rustc_transmute/src/layout/dfa.rs
@@ -266,7 +266,7 @@ where
     }
 
     #[cfg(test)]
-    pub(crate) fn from_edges<B: Copy + Into<Byte>>(
+    pub(crate) fn from_edges<B: Clone + Into<Byte>>(
         start: u32,
         accept: u32,
         edges: &[(u32, B, u32)],
@@ -275,8 +275,8 @@ where
         let accept = State(accept);
         let mut transitions: Map<State, Vec<(Byte, State)>> = Map::default();
 
-        for (src, edge, dst) in edges.iter().copied() {
-            transitions.entry(State(src)).or_default().push((edge.into(), State(dst)));
+        for &(src, ref edge, dst) in edges.iter() {
+            transitions.entry(State(src)).or_default().push((edge.clone().into(), State(dst)));
         }
 
         let transitions = transitions
@@ -401,12 +401,24 @@ mod edge_set {
             mut join: impl FnMut(Option<S>, Option<S>) -> S,
         ) -> EdgeSet<S>
         where
-            S: Copy,
+            S: Copy + Eq,
         {
+            let mut runs: SmallVec<[(Byte, S); 1]> = SmallVec::new();
             let xs = self.runs.iter().copied();
             let ys = other.runs.iter().copied();
-            // FIXME(@joshlf): Merge contiguous runs with common destination.
-            EdgeSet { runs: union(xs, ys).map(|(range, (x, y))| (range, join(x, y))).collect() }
+            for (range, (x, y)) in union(xs, ys) {
+                let state = join(x, y);
+                match runs.last_mut() {
+                    // Merge contiguous runs with a common destination.
+                    Some(&mut (ref mut last_range, ref mut last_state))
+                        if last_range.end == range.start && *last_state == state =>
+                    {
+                        last_range.end = range.end
+                    }
+                    _ => runs.push((range, state)),
+                }
+            }
+            EdgeSet { runs }
         }
     }
 }
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
index fbb4639dbd6..0227ad71ae6 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
@@ -314,7 +314,7 @@ mod union {
         let u = s.clone().union(t.clone(), new_state);
 
         let expected_u =
-            Dfa::from_edges(b, a, &[(b, 0, c), (b, 1, d), (d, 1, a), (d, 0, a), (c, 0, a)]);
+            Dfa::from_edges(b, a, &[(b, 0..=0, c), (b, 1..=1, d), (d, 0..=1, a), (c, 0..=0, a)]);
 
         assert_eq!(u, expected_u);