merge: rewrite bottom half of trivial_merge() for non-copyable types

The input values of trivial_merge() will be changed to Iterator<Item = T>
where T: Eq + Hash. It could be <Item = &'a T>, but it doesn't have to be.
This commit is contained in:
Yuya Nishihara 2023-11-05 10:40:55 +09:00
parent d8a7822c38
commit 01523ba4f3

View File

@ -72,31 +72,29 @@ where
// Collect non-zero value. Values with a count of 0 means that they have // Collect non-zero value. Values with a count of 0 means that they have
// cancelled out. // cancelled out.
let counts = counts counts.retain(|_, count| *count != 0);
.into_iter() if counts.len() == 1 {
.filter(|&(_, count)| count != 0) // If there is a single value with a count of 1 left, then that is the result.
.collect_vec(); let (value, count) = counts.into_iter().next().unwrap();
match counts[..] { assert_eq!(count, 1);
[(value, 1)] => { Some(value)
// If there is a single value with a count of 1 left, then that is the result. } else if counts.len() == 2 {
Some(value) // All sides made the same change.
// This matches what Git and Mercurial do (in the 3-way case at least), but not
// what Darcs and Pijul do. It means that repeated 3-way merging of multiple
// trees may give different results depending on the order of merging.
// TODO: Consider removing this special case, making the algorithm more strict,
// and maybe add a more lenient version that is used when the user explicitly
// asks for conflict resolution.
let ((value1, count1), (value2, count2)) = counts.into_iter().next_tuple().unwrap();
assert_eq!(count1 + count2, 1);
if count1 > 0 {
Some(value1)
} else {
Some(value2)
} }
[(value1, count1), (value2, count2)] => { } else {
// All sides made the same change. None
// This matches what Git and Mercurial do (in the 3-way case at least), but not
// what Darcs and Pijul do. It means that repeated 3-way merging of multiple
// trees may give different results depending on the order of merging.
// TODO: Consider removing this special case, making the algorithm more strict,
// and maybe add a more lenient version that is used when the user explicitly
// asks for conflict resolution.
assert_eq!(count1 + count2, 1);
if count1 > 0 {
Some(value1)
} else {
Some(value2)
}
}
_ => None,
} }
} }