diff --git a/compiler/rustc_transmute/src/layout/dfa.rs b/compiler/rustc_transmute/src/layout/dfa.rs index 05afa28db31a..6d072c336af2 100644 --- a/compiler/rustc_transmute/src/layout/dfa.rs +++ b/compiler/rustc_transmute/src/layout/dfa.rs @@ -266,7 +266,7 @@ pub(crate) fn refs_from(&self, start: State) -> impl Iterator } #[cfg(test)] - pub(crate) fn from_edges>( + pub(crate) fn from_edges>( start: u32, accept: u32, edges: &[(u32, B, u32)], @@ -275,8 +275,8 @@ pub(crate) fn from_edges>( let accept = State(accept); let mut transitions: Map> = 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 @@ pub(crate) fn union( mut join: impl FnMut(Option, Option) -> S, ) -> EdgeSet 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 fbb4639dbd63..0227ad71ae66 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs @@ -314,7 +314,7 @@ fn 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);