jj_lib/
merge.rs

1// Copyright 2023 The Jujutsu Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Generic algorithms for working with merged values, plus specializations for
16//! some common types of merged values.
17
18use std::borrow::Borrow;
19use std::collections::HashMap;
20use std::fmt::Debug;
21use std::fmt::Formatter;
22use std::fmt::Write as _;
23use std::future::Future;
24use std::hash::Hash;
25use std::iter::zip;
26use std::slice;
27use std::sync::Arc;
28
29use futures::future::try_join_all;
30use itertools::Itertools as _;
31use smallvec::SmallVec;
32use smallvec::smallvec_inline;
33
34use crate::backend::BackendResult;
35use crate::backend::CopyId;
36use crate::backend::FileId;
37use crate::backend::TreeValue;
38use crate::content_hash::ContentHash;
39use crate::content_hash::DigestUpdate;
40use crate::repo_path::RepoPath;
41use crate::repo_path::RepoPathComponent;
42use crate::store::Store;
43use crate::tree::Tree;
44
45/// A generic diff/transition from one value to another.
46///
47/// This is not a diff in the `patch(1)` sense. See `diff::ContentDiff` for
48/// that.
49#[derive(Copy, Clone, Debug, PartialEq, Eq)]
50pub struct Diff<T> {
51    /// The state before
52    pub before: T,
53    /// The state after
54    pub after: T,
55}
56
57impl<T> Diff<T> {
58    /// Create a new diff
59    pub fn new(before: T, after: T) -> Self {
60        Self { before, after }
61    }
62
63    /// Apply a function to both values
64    pub fn map<U>(self, mut f: impl FnMut(T) -> U) -> Diff<U> {
65        Diff {
66            before: f(self.before),
67            after: f(self.after),
68        }
69    }
70
71    /// Convert a `&Diff<T>` into a `Diff<&T>`.
72    pub fn as_ref(&self) -> Diff<&T> {
73        Diff {
74            before: &self.before,
75            after: &self.after,
76        }
77    }
78
79    /// Convert a diff into an array `[before, after]`.
80    pub fn into_array(self) -> [T; 2] {
81        [self.before, self.after]
82    }
83}
84
85impl<T: Eq> Diff<T> {
86    /// Whether the diff represents a change, i.e. if `before` and `after` are
87    /// not equal
88    pub fn is_changed(&self) -> bool {
89        self.before != self.after
90    }
91}
92
93/// Whether to resolve conflict that makes the same change at all sides.
94#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize)]
95#[serde(rename_all = "kebab-case")]
96pub enum SameChange {
97    /// Leaves same-change conflict unresolved.
98    Keep,
99    /// Resolves same-change conflict as if one side were unchanged.
100    /// (i.e. `A+(A-B)=A`)
101    ///
102    /// This matches what Git and Mercurial do (in the 3-way case at least), but
103    /// not what Darcs does. It means that repeated 3-way merging of multiple
104    /// trees may give different results depending on the order of merging.
105    Accept,
106}
107
108/// Attempt to resolve trivial conflicts between the inputs. There must be
109/// an odd number of terms.
110pub fn trivial_merge<T>(values: &[T], same_change: SameChange) -> Option<&T>
111where
112    T: Eq + Hash,
113{
114    assert!(
115        values.len() % 2 == 1,
116        "trivial_merge() requires an odd number of terms"
117    );
118    // Optimize the common cases of 3-way merge and 1-way (non-)merge
119    if let [add] = values {
120        return Some(add);
121    } else if let [add0, remove, add1] = values {
122        return if add0 == add1 && same_change == SameChange::Accept {
123            Some(add0)
124        } else if add0 == remove {
125            Some(add1)
126        } else if add1 == remove {
127            Some(add0)
128        } else {
129            None
130        };
131    }
132
133    // Number of occurrences of each value, with positive indexes counted as +1 and
134    // negative as -1, thereby letting positive and negative terms with the same
135    // value (i.e. key in the map) cancel each other.
136    let mut counts: HashMap<&T, i32> = HashMap::new();
137    for (value, n) in zip(values, [1, -1].into_iter().cycle()) {
138        counts.entry(value).and_modify(|e| *e += n).or_insert(n);
139    }
140
141    // Collect non-zero value. Values with a count of 0 means that they have
142    // canceled out.
143    counts.retain(|_, count| *count != 0);
144    if counts.len() == 1 {
145        // If there is a single value with a count of 1 left, then that is the result.
146        let (value, count) = counts.into_iter().next().unwrap();
147        assert_eq!(count, 1);
148        Some(value)
149    } else if counts.len() == 2 && same_change == SameChange::Accept {
150        // All sides made the same change.
151        let [(value1, count1), (value2, count2)] = counts.into_iter().next_array().unwrap();
152        assert_eq!(count1 + count2, 1);
153        if count1 > 0 {
154            Some(value1)
155        } else {
156            Some(value2)
157        }
158    } else {
159        None
160    }
161}
162
163/// A generic representation of merged values.
164///
165/// There is exactly one more `adds()` than `removes()`. When interpreted as a
166/// series of diffs, the merge's (i+1)-st add is matched with the i-th
167/// remove. The zeroth add is considered a diff from the non-existent state.
168#[derive(PartialEq, Eq, Hash, Clone, serde::Serialize)]
169#[serde(transparent)]
170pub struct Merge<T> {
171    /// Alternates between positive and negative terms, starting with positive.
172    values: SmallVec<[T; 1]>,
173}
174
175impl<T: Debug> Debug for Merge<T> {
176    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
177        // Format like an enum with two variants to make it less verbose in the common
178        // case of a resolved state.
179        if let Some(value) = self.as_resolved() {
180            f.debug_tuple("Resolved").field(value).finish()
181        } else {
182            f.debug_tuple("Conflicted").field(&self.values).finish()
183        }
184    }
185}
186
187impl<T> Merge<T> {
188    /// Creates a `Merge` from the given values, in which positive and negative
189    /// terms alternate.
190    pub fn from_vec(values: impl Into<SmallVec<[T; 1]>>) -> Self {
191        let values = values.into();
192        assert!(values.len() % 2 != 0, "must have an odd number of terms");
193        Self { values }
194    }
195
196    /// Creates a new merge object from the given removes and adds.
197    pub fn from_removes_adds(
198        removes: impl IntoIterator<Item = T>,
199        adds: impl IntoIterator<Item = T>,
200    ) -> Self {
201        let removes = removes.into_iter();
202        let mut adds = adds.into_iter();
203        let mut values = SmallVec::with_capacity(removes.size_hint().0 * 2 + 1);
204        values.push(adds.next().expect("must have at least one add"));
205        for diff in removes.zip_longest(adds) {
206            let (remove, add) = diff.both().expect("must have one more adds than removes");
207            values.extend([remove, add]);
208        }
209        Self { values }
210    }
211
212    /// Creates a `Merge` with a single resolved value.
213    pub const fn resolved(value: T) -> Self {
214        Self {
215            values: smallvec_inline![value],
216        }
217    }
218
219    /// Create a `Merge` from a `removes` and `adds`, padding with `None` to
220    /// make sure that there is exactly one more `adds` than `removes`.
221    pub fn from_legacy_form(
222        removes: impl IntoIterator<Item = T>,
223        adds: impl IntoIterator<Item = T>,
224    ) -> Merge<Option<T>> {
225        let removes = removes.into_iter();
226        let mut adds = adds.into_iter().fuse();
227        let mut values = smallvec_inline![adds.next()];
228        for diff in removes.zip_longest(adds) {
229            let (remove, add) = diff.map_any(Some, Some).or_default();
230            values.extend([remove, add]);
231        }
232        Merge { values }
233    }
234
235    /// The removed values, also called negative terms.
236    pub fn removes(&self) -> impl ExactSizeIterator<Item = &T> {
237        self.values[1..].iter().step_by(2)
238    }
239
240    /// The added values, also called positive terms.
241    pub fn adds(&self) -> impl ExactSizeIterator<Item = &T> {
242        self.values.iter().step_by(2)
243    }
244
245    /// Returns the zeroth added value, which is guaranteed to exist.
246    pub fn first(&self) -> &T {
247        &self.values[0]
248    }
249
250    /// Returns the `index`-th removed value, which is considered belonging to
251    /// the `index`-th diff pair.
252    pub fn get_remove(&self, index: usize) -> Option<&T> {
253        self.values.get(index * 2 + 1)
254    }
255
256    /// Returns the `index`-th added value, which is considered belonging to the
257    /// `index-1`-th diff pair. The zeroth add is a diff from the non-existent
258    /// state.
259    pub fn get_add(&self, index: usize) -> Option<&T> {
260        self.values.get(index * 2)
261    }
262
263    /// Removes the specified "removed"/"added" values. The removed slots are
264    /// replaced by the last "removed"/"added" values.
265    pub fn swap_remove(&mut self, remove_index: usize, add_index: usize) -> (T, T) {
266        // Swap with the last "added" and "removed" values in order.
267        let add = self.values.swap_remove(add_index * 2);
268        let remove = self.values.swap_remove(remove_index * 2 + 1);
269        (remove, add)
270    }
271
272    /// The number of positive terms in the conflict.
273    pub fn num_sides(&self) -> usize {
274        self.values.len() / 2 + 1
275    }
276
277    /// Whether this merge is resolved. Does not resolve trivial merges.
278    pub fn is_resolved(&self) -> bool {
279        self.values.len() == 1
280    }
281
282    /// Returns the resolved value, if this merge is resolved. Does not
283    /// resolve trivial merges.
284    pub fn as_resolved(&self) -> Option<&T> {
285        if let [value] = &self.values[..] {
286            Some(value)
287        } else {
288            None
289        }
290    }
291
292    /// Returns the resolved value, if this merge is resolved. Otherwise returns
293    /// the merge itself as an `Err`. Does not resolve trivial merges.
294    pub fn into_resolved(mut self) -> Result<T, Self> {
295        if self.values.len() == 1 {
296            Ok(self.values.pop().unwrap())
297        } else {
298            Err(self)
299        }
300    }
301
302    /// Returns a vector mapping of a value's index in the simplified merge to
303    /// its original index in the unsimplified merge.
304    ///
305    /// The merge is simplified by removing identical values in add and remove
306    /// values.
307    fn get_simplified_mapping(&self) -> Vec<usize>
308    where
309        T: PartialEq,
310    {
311        let unsimplified_len = self.values.len();
312        let mut simplified_to_original_indices = (0..unsimplified_len).collect_vec();
313
314        let mut add_index = 0;
315        while add_index < simplified_to_original_indices.len() {
316            let add = &self.values[simplified_to_original_indices[add_index]];
317            let mut remove_indices = simplified_to_original_indices
318                .iter()
319                .enumerate()
320                .skip(1)
321                .step_by(2);
322            if let Some((remove_index, _)) = remove_indices
323                .find(|&(_, original_remove_index)| &self.values[*original_remove_index] == add)
324            {
325                // Align the current "add" value to the `remove_index/2`-th diff, then
326                // delete the diff pair.
327                simplified_to_original_indices.swap(remove_index + 1, add_index);
328                simplified_to_original_indices.drain(remove_index..remove_index + 2);
329            } else {
330                add_index += 2;
331            }
332        }
333
334        simplified_to_original_indices
335    }
336
337    /// Simplify the merge by joining diffs like A->B and B->C into A->C.
338    /// Also drops trivial diffs like A->A.
339    #[must_use]
340    pub fn simplify(&self) -> Self
341    where
342        T: PartialEq + Clone,
343    {
344        let mapping = self.get_simplified_mapping();
345        // Reorder values based on their new indices in the simplified merge.
346        let values = mapping
347            .iter()
348            .map(|index| self.values[*index].clone())
349            .collect();
350        Self { values }
351    }
352
353    /// Updates the merge based on the given simplified merge.
354    pub fn update_from_simplified(mut self, simplified: Self) -> Self
355    where
356        T: PartialEq,
357    {
358        let mapping = self.get_simplified_mapping();
359        assert_eq!(mapping.len(), simplified.values.len());
360        for (index, value) in mapping.into_iter().zip(simplified.values.into_iter()) {
361            self.values[index] = value;
362        }
363        self
364    }
365
366    /// If this merge can be trivially resolved, returns the value it resolves
367    /// to.
368    pub fn resolve_trivial(&self, same_change: SameChange) -> Option<&T>
369    where
370        T: Eq + Hash,
371    {
372        trivial_merge(&self.values, same_change)
373    }
374
375    /// Pads this merge with to the specified number of sides with the specified
376    /// value. No-op if the requested size is not larger than the current size.
377    pub fn pad_to(&mut self, num_sides: usize, value: &T)
378    where
379        T: Clone,
380    {
381        if num_sides <= self.num_sides() {
382            return;
383        }
384        self.values.resize(num_sides * 2 - 1, value.clone());
385    }
386
387    /// Returns a slice containing the terms. The items will alternate between
388    /// positive and negative terms, starting with positive (since there's one
389    /// more of those).
390    pub fn as_slice(&self) -> &[T] {
391        &self.values
392    }
393
394    /// Returns an iterator over references to the terms. The items will
395    /// alternate between positive and negative terms, starting with
396    /// positive (since there's one more of those).
397    pub fn iter(&self) -> slice::Iter<'_, T> {
398        self.values.iter()
399    }
400
401    /// A version of `Merge::iter()` that iterates over mutable references.
402    pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
403        self.values.iter_mut()
404    }
405
406    /// Creates a new merge by applying `f` to each remove and add.
407    pub fn map<'a, U>(&'a self, f: impl FnMut(&'a T) -> U) -> Merge<U> {
408        let values = self.values.iter().map(f).collect();
409        Merge { values }
410    }
411
412    /// Creates a new merge by applying `f` to each remove and add, returning
413    /// `Err if `f` returns `Err` for any of them.
414    pub fn try_map<'a, U, E>(
415        &'a self,
416        f: impl FnMut(&'a T) -> Result<U, E>,
417    ) -> Result<Merge<U>, E> {
418        let values = self.values.iter().map(f).try_collect()?;
419        Ok(Merge { values })
420    }
421
422    /// Creates a new merge by applying the async function `f` to each remove
423    /// and add, running them concurrently, and returning `Err if `f`
424    /// returns `Err` for any of them.
425    pub async fn try_map_async<'a, F, U, E>(
426        &'a self,
427        f: impl FnMut(&'a T) -> F,
428    ) -> Result<Merge<U>, E>
429    where
430        F: Future<Output = Result<U, E>>,
431    {
432        let values = try_join_all(self.values.iter().map(f)).await?;
433        Ok(Merge {
434            values: values.into(),
435        })
436    }
437}
438
439/// Helper for consuming items from an iterator and then creating a `Merge`.
440///
441/// By not collecting directly into `Merge`, we can avoid creating invalid
442/// instances of it. If we had `Merge::from_iter()` we would need to allow it to
443/// accept iterators of any length (including 0). We couldn't make it panic on
444/// even lengths because we can get passed such iterators from e.g.
445/// `Option::from_iter()`. By collecting into `MergeBuilder` instead, we move
446/// the checking until after `from_iter()` (to `MergeBuilder::build()`).
447#[derive(Clone, Debug, PartialEq, Eq)]
448pub struct MergeBuilder<T> {
449    values: SmallVec<[T; 1]>,
450}
451
452impl<T> Default for MergeBuilder<T> {
453    fn default() -> Self {
454        Self {
455            values: Default::default(),
456        }
457    }
458}
459
460impl<T> MergeBuilder<T> {
461    /// Requires that exactly one more "adds" than "removes" have been added to
462    /// this builder.
463    pub fn build(self) -> Merge<T> {
464        Merge::from_vec(self.values)
465    }
466}
467
468impl<T> IntoIterator for Merge<T> {
469    type Item = T;
470    type IntoIter = smallvec::IntoIter<[T; 1]>;
471
472    fn into_iter(self) -> Self::IntoIter {
473        self.values.into_iter()
474    }
475}
476
477impl<T> FromIterator<T> for MergeBuilder<T> {
478    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
479        let mut builder = Self::default();
480        builder.extend(iter);
481        builder
482    }
483}
484
485impl<T> Extend<T> for MergeBuilder<T> {
486    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
487        self.values.extend(iter);
488    }
489}
490
491impl<T> Merge<Option<T>> {
492    /// Creates a resolved merge with a value of `None`.
493    pub fn absent() -> Self {
494        Self::resolved(None)
495    }
496
497    /// Creates a resolved merge with a value of `Some(value)`.
498    pub fn normal(value: T) -> Self {
499        Self::resolved(Some(value))
500    }
501
502    /// Whether this represents a resolved value of `None`.
503    pub fn is_absent(&self) -> bool {
504        matches!(self.as_resolved(), Some(None))
505    }
506
507    /// The opposite of `is_absent()`.
508    pub fn is_present(&self) -> bool {
509        !self.is_absent()
510    }
511
512    /// Returns the value if this is present and non-conflicting.
513    pub fn as_normal(&self) -> Option<&T> {
514        self.as_resolved()?.as_ref()
515    }
516
517    /// Creates lists of `removes` and `adds` from a `Merge` by dropping
518    /// `None` values. Note that the conversion is lossy: the order of `None`
519    /// values is not preserved when converting back to a `Merge`.
520    pub fn into_legacy_form(self) -> (Vec<T>, Vec<T>) {
521        // Allocate the maximum size assuming there would be few `None`s.
522        let mut removes = Vec::with_capacity(self.values.len() / 2);
523        let mut adds = Vec::with_capacity(self.values.len() / 2 + 1);
524        let mut values = self.values.into_iter();
525        adds.extend(values.next().unwrap());
526        while let Some(remove) = values.next() {
527            removes.extend(remove);
528            adds.extend(values.next().unwrap());
529        }
530        (removes, adds)
531    }
532}
533
534impl<T: Clone> Merge<Option<&T>> {
535    /// Creates a new merge by cloning inner `Option<&T>`s.
536    pub fn cloned(&self) -> Merge<Option<T>> {
537        self.map(|value| value.cloned())
538    }
539}
540
541impl<T> Merge<Merge<T>> {
542    /// Flattens a nested merge into a regular merge.
543    ///
544    /// Let's say we have a 3-way merge of 3-way merges like this:
545    ///
546    /// ```text
547    /// 4 5   7 8
548    ///  3     6
549    ///    1 2
550    ///     0
551    /// ```
552    ///
553    /// Flattening that results in this 9-way merge:
554    ///
555    /// ```text
556    /// 4 5 0 7 8
557    ///  3 2 1 6
558    /// ```
559    pub fn flatten(self) -> Merge<T> {
560        let mut outer_values = self.values.into_iter();
561        let mut result = outer_values.next().unwrap();
562        while let Some(mut remove) = outer_values.next() {
563            // Add removes reversed, and with the first element moved last, so we preserve
564            // the diffs
565            remove.values.rotate_left(1);
566            for i in 0..remove.values.len() / 2 {
567                remove.values.swap(i * 2, i * 2 + 1);
568            }
569            result.values.extend(remove.values);
570            let add = outer_values.next().unwrap();
571            result.values.extend(add.values);
572        }
573        result
574    }
575}
576
577impl<T: ContentHash> ContentHash for Merge<T> {
578    fn hash(&self, state: &mut impl DigestUpdate) {
579        self.values.hash(state);
580    }
581}
582
583/// Borrowed `MergedTreeValue`.
584pub type MergedTreeVal<'a> = Merge<Option<&'a TreeValue>>;
585
586/// The value at a given path in a commit.
587///
588/// It depends on the context whether it can be absent
589/// (`Merge::is_absent()`). For example, when getting the value at a
590/// specific path, it may be, but when iterating over entries in a
591/// tree, it shouldn't be.
592pub type MergedTreeValue = Merge<Option<TreeValue>>;
593
594impl<T> Merge<Option<T>>
595where
596    T: Borrow<TreeValue>,
597{
598    /// Whether this merge should be recursed into when doing directory walks.
599    pub fn is_tree(&self) -> bool {
600        self.is_present()
601            && self.iter().all(|value| {
602                matches!(
603                    borrow_tree_value(value.as_ref()),
604                    Some(TreeValue::Tree(_)) | None
605                )
606            })
607    }
608
609    /// Whether this merge is present and not a tree
610    pub fn is_file_like(&self) -> bool {
611        self.is_present() && !self.is_tree()
612    }
613
614    /// If this merge contains only files or absent entries, returns a merge of
615    /// the `FileId`s. The executable bits and copy IDs will be ignored. Use
616    /// `Merge::with_new_file_ids()` to produce a new merge with the original
617    /// executable bits preserved.
618    pub fn to_file_merge(&self) -> Option<Merge<Option<FileId>>> {
619        let file_ids = self
620            .try_map(|term| match borrow_tree_value(term.as_ref()) {
621                None => Ok(None),
622                Some(TreeValue::File {
623                    id,
624                    executable: _,
625                    copy_id: _,
626                }) => Ok(Some(id.clone())),
627                _ => Err(()),
628            })
629            .ok()?;
630
631        Some(file_ids)
632    }
633
634    /// If this merge contains only files or absent entries, returns a merge of
635    /// the files' executable bits.
636    pub fn to_executable_merge(&self) -> Option<Merge<Option<bool>>> {
637        self.try_map(|term| match borrow_tree_value(term.as_ref()) {
638            None => Ok(None),
639            Some(TreeValue::File {
640                id: _,
641                executable,
642                copy_id: _,
643            }) => Ok(Some(*executable)),
644            _ => Err(()),
645        })
646        .ok()
647    }
648
649    /// If this merge contains only files or absent entries, returns a merge of
650    /// the files' copy IDs.
651    pub fn to_copy_id_merge(&self) -> Option<Merge<Option<CopyId>>> {
652        self.try_map(|term| match borrow_tree_value(term.as_ref()) {
653            None => Ok(None),
654            Some(TreeValue::File {
655                id: _,
656                executable: _,
657                copy_id,
658            }) => Ok(Some(copy_id.clone())),
659            _ => Err(()),
660        })
661        .ok()
662    }
663
664    /// If every non-`None` term of a `MergedTreeValue`
665    /// is a `TreeValue::Tree`, this converts it to
666    /// a `Merge<Tree>`, with empty trees instead of
667    /// any `None` terms. Otherwise, returns `None`.
668    pub async fn to_tree_merge(
669        &self,
670        store: &Arc<Store>,
671        dir: &RepoPath,
672    ) -> BackendResult<Option<Merge<Tree>>> {
673        let tree_id_merge = self.try_map(|term| match borrow_tree_value(term.as_ref()) {
674            None => Ok(None),
675            Some(TreeValue::Tree(id)) => Ok(Some(id)),
676            Some(_) => Err(()),
677        });
678        if let Ok(tree_id_merge) = tree_id_merge {
679            Ok(Some(
680                tree_id_merge
681                    .try_map_async(async |id| {
682                        if let Some(id) = id {
683                            store.get_tree_async(dir.to_owned(), id).await
684                        } else {
685                            Ok(Tree::empty(store.clone(), dir.to_owned()))
686                        }
687                    })
688                    .await?,
689            ))
690        } else {
691            Ok(None)
692        }
693    }
694
695    /// Creates a new merge with the file ids from the given merge. In other
696    /// words, only the executable bits from `self` will be preserved.
697    ///
698    /// The given `file_ids` should have the same shape as `self`. Only the
699    /// `FileId` values may differ.
700    pub fn with_new_file_ids(&self, file_ids: &Merge<Option<FileId>>) -> Merge<Option<TreeValue>> {
701        assert_eq!(self.values.len(), file_ids.values.len());
702        let values = zip(self.iter(), file_ids.iter().cloned())
703            .map(
704                |(tree_value, file_id)| match (borrow_tree_value(tree_value.as_ref()), file_id) {
705                    (
706                        Some(TreeValue::File {
707                            id: _,
708                            executable,
709                            copy_id,
710                        }),
711                        Some(id),
712                    ) => Some(TreeValue::File {
713                        id,
714                        executable: *executable,
715                        copy_id: copy_id.clone(),
716                    }),
717                    (None, None) => None,
718                    (old, new) => panic!("incompatible update: {old:?} to {new:?}"),
719                },
720            )
721            .collect();
722        Merge { values }
723    }
724
725    /// Give a summary description of the conflict's "removes" and "adds"
726    pub fn describe(&self) -> String {
727        let mut buf = String::new();
728        writeln!(buf, "Conflict:").unwrap();
729        for term in self.removes().flatten() {
730            writeln!(buf, "  Removing {}", describe_conflict_term(term.borrow())).unwrap();
731        }
732        for term in self.adds().flatten() {
733            writeln!(buf, "  Adding {}", describe_conflict_term(term.borrow())).unwrap();
734        }
735        buf
736    }
737}
738
739fn borrow_tree_value<T: Borrow<TreeValue> + ?Sized>(term: Option<&T>) -> Option<&TreeValue> {
740    term.map(|value| value.borrow())
741}
742
743fn describe_conflict_term(value: &TreeValue) -> String {
744    match value {
745        TreeValue::File {
746            id,
747            executable: false,
748            copy_id: _,
749        } => {
750            // TODO: include the copy here once we start using it
751            format!("file with id {id}")
752        }
753        TreeValue::File {
754            id,
755            executable: true,
756            copy_id: _,
757        } => {
758            // TODO: include the copy here once we start using it
759            format!("executable file with id {id}")
760        }
761        TreeValue::Symlink(id) => {
762            format!("symlink with id {id}")
763        }
764        TreeValue::Tree(id) => {
765            format!("tree with id {id}")
766        }
767        TreeValue::GitSubmodule(id) => {
768            format!("Git submodule with id {id}")
769        }
770    }
771}
772
773impl Merge<Tree> {
774    /// The directory that is shared by all trees in the merge.
775    pub fn dir(&self) -> &RepoPath {
776        debug_assert!(self.iter().map(|tree| tree.dir()).all_equal());
777        self.first().dir()
778    }
779
780    /// The value at the given basename. The value can be `Resolved` even if
781    /// `self` is conflicted, which happens if the value at the path can be
782    /// trivially merged. Does not recurse, so if `basename` refers to a Tree,
783    /// then a `TreeValue::Tree` will be returned.
784    pub fn value(&self, basename: &RepoPathComponent) -> MergedTreeVal<'_> {
785        if let Some(tree) = self.as_resolved() {
786            return Merge::resolved(tree.value(basename));
787        }
788        let same_change = self.first().store().merge_options().same_change;
789        let value = self.map(|tree| tree.value(basename));
790        if let Some(resolved) = value.resolve_trivial(same_change) {
791            return Merge::resolved(*resolved);
792        }
793        value
794    }
795
796    /// Gets the `Merge<Tree>` in a subdirectory of the current tree. If the
797    /// path doesn't correspond to a tree in any of the inputs to the merge,
798    /// then that entry will be replaced by an empty tree in the result.
799    pub async fn sub_tree(&self, name: &RepoPathComponent) -> BackendResult<Option<Self>> {
800        let store = self.first().store();
801        match self.value(name).into_resolved() {
802            Ok(Some(TreeValue::Tree(sub_tree_id))) => {
803                let subdir = self.dir().join(name);
804                Ok(Some(Self::resolved(
805                    store.get_tree_async(subdir, sub_tree_id).await?,
806                )))
807            }
808            Ok(_) => Ok(None),
809            Err(merge) => {
810                if !merge.is_tree() {
811                    return Ok(None);
812                }
813                let trees = merge
814                    .try_map_async(async |value| match value {
815                        Some(TreeValue::Tree(sub_tree_id)) => {
816                            let subdir = self.dir().join(name);
817                            store.get_tree_async(subdir, sub_tree_id).await
818                        }
819                        Some(_) => unreachable!(),
820                        None => {
821                            let subdir = self.dir().join(name);
822                            Ok(Tree::empty(store.clone(), subdir))
823                        }
824                    })
825                    .await?;
826                Ok(Some(trees))
827            }
828        }
829    }
830
831    /// Look up the tree at the given path.
832    pub async fn sub_tree_recursive(&self, path: &RepoPath) -> BackendResult<Option<Self>> {
833        let mut current_tree = self.clone();
834        for name in path.components() {
835            match current_tree.sub_tree(name).await? {
836                None => {
837                    return Ok(None);
838                }
839                Some(sub_tree) => {
840                    current_tree = sub_tree;
841                }
842            }
843        }
844        Ok(Some(current_tree))
845    }
846}
847
848#[cfg(test)]
849mod tests {
850    use test_case::test_case;
851
852    use super::*;
853
854    fn c<T: Clone>(terms: &[T]) -> Merge<T> {
855        Merge::from_vec(terms.to_vec())
856    }
857
858    #[test_case(SameChange::Keep)]
859    #[test_case(SameChange::Accept)]
860    fn test_trivial_merge(same_change: SameChange) {
861        let accept_same_change = same_change == SameChange::Accept;
862        let merge = |values| trivial_merge(values, same_change);
863        assert_eq!(merge(&[0]), Some(&0));
864        assert_eq!(merge(&[0, 0, 0]), Some(&0));
865        assert_eq!(merge(&[0, 0, 1]), Some(&1));
866        assert_eq!(merge(&[0, 1, 0]), accept_same_change.then_some(&0));
867        assert_eq!(merge(&[0, 1, 1]), Some(&0));
868        assert_eq!(merge(&[0, 1, 2]), None);
869        assert_eq!(merge(&[0, 0, 0, 0, 0]), Some(&0));
870        assert_eq!(merge(&[0, 0, 0, 0, 1]), Some(&1));
871        assert_eq!(merge(&[0, 0, 0, 1, 0]), accept_same_change.then_some(&0));
872        assert_eq!(merge(&[0, 0, 0, 1, 1]), Some(&0));
873        assert_eq!(merge(&[0, 0, 0, 1, 2]), None);
874        assert_eq!(merge(&[0, 0, 1, 0, 0]), Some(&1));
875        assert_eq!(merge(&[0, 0, 1, 0, 1]), accept_same_change.then_some(&1));
876        assert_eq!(merge(&[0, 0, 1, 0, 2]), None);
877        assert_eq!(merge(&[0, 0, 1, 1, 0]), Some(&0));
878        assert_eq!(merge(&[0, 0, 1, 1, 1]), Some(&1));
879        assert_eq!(merge(&[0, 0, 1, 1, 2]), Some(&2));
880        assert_eq!(merge(&[0, 0, 1, 2, 0]), None);
881        assert_eq!(merge(&[0, 0, 1, 2, 1]), accept_same_change.then_some(&1));
882        assert_eq!(merge(&[0, 0, 1, 2, 2]), Some(&1));
883        assert_eq!(merge(&[0, 0, 1, 2, 3]), None);
884        assert_eq!(merge(&[0, 1, 0, 0, 0]), accept_same_change.then_some(&0));
885        assert_eq!(merge(&[0, 1, 0, 0, 1]), Some(&0));
886        assert_eq!(merge(&[0, 1, 0, 0, 2]), None);
887        assert_eq!(merge(&[0, 1, 0, 1, 0]), accept_same_change.then_some(&0));
888        assert_eq!(merge(&[0, 1, 0, 1, 1]), accept_same_change.then_some(&0));
889        assert_eq!(merge(&[0, 1, 0, 1, 2]), None);
890        assert_eq!(merge(&[0, 1, 0, 2, 0]), None);
891        assert_eq!(merge(&[0, 1, 0, 2, 1]), accept_same_change.then_some(&0));
892        assert_eq!(merge(&[0, 1, 0, 2, 2]), accept_same_change.then_some(&0));
893        assert_eq!(merge(&[0, 1, 0, 2, 3]), None);
894        assert_eq!(merge(&[0, 1, 1, 0, 0]), Some(&0));
895        assert_eq!(merge(&[0, 1, 1, 0, 1]), Some(&1));
896        assert_eq!(merge(&[0, 1, 1, 0, 2]), Some(&2));
897        assert_eq!(merge(&[0, 1, 1, 1, 0]), accept_same_change.then_some(&0));
898        assert_eq!(merge(&[0, 1, 1, 1, 1]), Some(&0));
899        assert_eq!(merge(&[0, 1, 1, 1, 2]), None);
900        assert_eq!(merge(&[0, 1, 1, 2, 0]), accept_same_change.then_some(&0));
901        assert_eq!(merge(&[0, 1, 1, 2, 1]), None);
902        assert_eq!(merge(&[0, 1, 1, 2, 2]), Some(&0));
903        assert_eq!(merge(&[0, 1, 1, 2, 3]), None);
904        assert_eq!(merge(&[0, 1, 2, 0, 0]), None);
905        assert_eq!(merge(&[0, 1, 2, 0, 1]), Some(&2));
906        assert_eq!(merge(&[0, 1, 2, 0, 2]), accept_same_change.then_some(&2));
907        assert_eq!(merge(&[0, 1, 2, 0, 3]), None);
908        assert_eq!(merge(&[0, 1, 2, 1, 0]), None);
909        assert_eq!(merge(&[0, 1, 2, 1, 1]), None);
910        assert_eq!(merge(&[0, 1, 2, 1, 2]), None);
911        assert_eq!(merge(&[0, 1, 2, 1, 3]), None);
912        assert_eq!(merge(&[0, 1, 2, 2, 0]), accept_same_change.then_some(&0));
913        assert_eq!(merge(&[0, 1, 2, 2, 1]), Some(&0));
914        assert_eq!(merge(&[0, 1, 2, 2, 2]), None);
915        assert_eq!(merge(&[0, 1, 2, 2, 3]), None);
916        assert_eq!(merge(&[0, 1, 2, 3, 0]), None);
917        assert_eq!(merge(&[0, 1, 2, 3, 1]), None);
918        assert_eq!(merge(&[0, 1, 2, 3, 2]), None);
919        assert_eq!(merge(&[0, 1, 2, 3, 3]), None);
920        assert_eq!(merge(&[0, 1, 2, 3, 4]), None);
921    }
922
923    #[test]
924    fn test_legacy_form_conversion() {
925        fn test_equivalent<T>(legacy_form: (Vec<T>, Vec<T>), merge: Merge<Option<T>>)
926        where
927            T: Clone + PartialEq + std::fmt::Debug,
928        {
929            assert_eq!(merge.clone().into_legacy_form(), legacy_form);
930            assert_eq!(Merge::from_legacy_form(legacy_form.0, legacy_form.1), merge);
931        }
932        // Non-conflict
933        test_equivalent(
934            (vec![], vec![0]),
935            Merge::from_removes_adds(vec![], vec![Some(0)]),
936        );
937        // Regular 3-way conflict
938        test_equivalent(
939            (vec![0], vec![1, 2]),
940            Merge::from_removes_adds(vec![Some(0)], vec![Some(1), Some(2)]),
941        );
942        // Modify/delete conflict
943        test_equivalent(
944            (vec![0], vec![1]),
945            Merge::from_removes_adds(vec![Some(0)], vec![Some(1), None]),
946        );
947        // Add/add conflict
948        test_equivalent(
949            (vec![], vec![0, 1]),
950            Merge::from_removes_adds(vec![None], vec![Some(0), Some(1)]),
951        );
952        // 5-way conflict
953        test_equivalent(
954            (vec![0, 1], vec![2, 3, 4]),
955            Merge::from_removes_adds(vec![Some(0), Some(1)], vec![Some(2), Some(3), Some(4)]),
956        );
957        // 5-way delete/delete conflict
958        test_equivalent(
959            (vec![0, 1], vec![]),
960            Merge::from_removes_adds(vec![Some(0), Some(1)], vec![None, None, None]),
961        );
962    }
963
964    #[test]
965    fn test_as_resolved() {
966        assert_eq!(
967            Merge::from_removes_adds(vec![], vec![0]).as_resolved(),
968            Some(&0)
969        );
970        // Even a trivially resolvable merge is not resolved
971        assert_eq!(
972            Merge::from_removes_adds(vec![0], vec![0, 1]).as_resolved(),
973            None
974        );
975    }
976
977    #[test]
978    fn test_get_simplified_mapping() {
979        // 1-way merge
980        assert_eq!(c(&[0]).get_simplified_mapping(), vec![0]);
981        // 3-way merge
982        assert_eq!(c(&[0, 0, 0]).get_simplified_mapping(), vec![2]);
983        assert_eq!(c(&[0, 0, 1]).get_simplified_mapping(), vec![2]);
984        assert_eq!(c(&[0, 1, 0]).get_simplified_mapping(), vec![0, 1, 2]);
985        assert_eq!(c(&[0, 1, 1]).get_simplified_mapping(), vec![0]);
986        assert_eq!(c(&[0, 1, 2]).get_simplified_mapping(), vec![0, 1, 2]);
987        // 5-way merge
988        assert_eq!(c(&[0, 0, 0, 0, 0]).get_simplified_mapping(), vec![4]);
989        assert_eq!(c(&[0, 0, 0, 0, 1]).get_simplified_mapping(), vec![4]);
990        assert_eq!(c(&[0, 0, 0, 1, 0]).get_simplified_mapping(), vec![2, 3, 4]);
991        assert_eq!(c(&[0, 0, 0, 1, 1]).get_simplified_mapping(), vec![2]);
992        assert_eq!(c(&[0, 0, 0, 1, 2]).get_simplified_mapping(), vec![2, 3, 4]);
993        assert_eq!(c(&[0, 0, 1, 0, 0]).get_simplified_mapping(), vec![2]);
994        assert_eq!(c(&[0, 0, 1, 0, 1]).get_simplified_mapping(), vec![2, 3, 4]);
995        assert_eq!(c(&[0, 0, 1, 0, 2]).get_simplified_mapping(), vec![2, 3, 4]);
996        assert_eq!(c(&[0, 0, 1, 1, 0]).get_simplified_mapping(), vec![4]);
997        assert_eq!(c(&[0, 0, 1, 1, 1]).get_simplified_mapping(), vec![4]);
998        assert_eq!(c(&[0, 0, 1, 1, 2]).get_simplified_mapping(), vec![4]);
999        assert_eq!(c(&[0, 0, 2, 1, 0]).get_simplified_mapping(), vec![2, 3, 4]);
1000        assert_eq!(c(&[0, 0, 2, 1, 1]).get_simplified_mapping(), vec![2]);
1001        assert_eq!(c(&[0, 0, 2, 1, 2]).get_simplified_mapping(), vec![2, 3, 4]);
1002        assert_eq!(c(&[0, 0, 2, 1, 3]).get_simplified_mapping(), vec![2, 3, 4]);
1003        assert_eq!(c(&[0, 1, 0, 0, 0]).get_simplified_mapping(), vec![4, 1, 2]);
1004        assert_eq!(c(&[0, 1, 0, 0, 1]).get_simplified_mapping(), vec![2]);
1005        assert_eq!(c(&[0, 1, 0, 0, 2]).get_simplified_mapping(), vec![4, 1, 2]);
1006        assert_eq!(
1007            c(&[0, 1, 0, 1, 0]).get_simplified_mapping(),
1008            vec![0, 1, 2, 3, 4]
1009        );
1010        assert_eq!(c(&[0, 1, 0, 1, 1]).get_simplified_mapping(), vec![0, 3, 2]);
1011        assert_eq!(
1012            c(&[0, 1, 0, 1, 2]).get_simplified_mapping(),
1013            vec![0, 1, 2, 3, 4]
1014        );
1015        assert_eq!(
1016            c(&[0, 1, 0, 2, 0]).get_simplified_mapping(),
1017            vec![0, 1, 2, 3, 4]
1018        );
1019        assert_eq!(c(&[0, 1, 0, 2, 1]).get_simplified_mapping(), vec![0, 3, 2]);
1020        assert_eq!(c(&[0, 1, 0, 2, 2]).get_simplified_mapping(), vec![0, 1, 2]);
1021        assert_eq!(
1022            c(&[0, 1, 0, 2, 3]).get_simplified_mapping(),
1023            vec![0, 1, 2, 3, 4]
1024        );
1025        assert_eq!(c(&[0, 1, 1, 0, 0]).get_simplified_mapping(), vec![4]);
1026        assert_eq!(c(&[0, 1, 1, 0, 1]).get_simplified_mapping(), vec![2]);
1027        assert_eq!(c(&[0, 1, 1, 0, 2]).get_simplified_mapping(), vec![4]);
1028        assert_eq!(c(&[0, 1, 1, 1, 0]).get_simplified_mapping(), vec![0, 3, 4]);
1029        assert_eq!(c(&[0, 1, 1, 1, 1]).get_simplified_mapping(), vec![0]);
1030        assert_eq!(c(&[0, 1, 1, 1, 2]).get_simplified_mapping(), vec![0, 3, 4]);
1031        assert_eq!(c(&[0, 1, 1, 2, 0]).get_simplified_mapping(), vec![0, 3, 4]);
1032        assert_eq!(c(&[0, 1, 1, 2, 1]).get_simplified_mapping(), vec![0, 3, 4]);
1033        assert_eq!(c(&[0, 1, 1, 2, 2]).get_simplified_mapping(), vec![0]);
1034        assert_eq!(c(&[0, 1, 1, 2, 3]).get_simplified_mapping(), vec![0, 3, 4]);
1035        assert_eq!(c(&[0, 1, 2, 0, 0]).get_simplified_mapping(), vec![4, 1, 2]);
1036        assert_eq!(c(&[0, 1, 2, 0, 1]).get_simplified_mapping(), vec![2]);
1037        assert_eq!(c(&[0, 1, 2, 0, 2]).get_simplified_mapping(), vec![4, 1, 2]);
1038        assert_eq!(c(&[0, 1, 2, 0, 3]).get_simplified_mapping(), vec![4, 1, 2]);
1039        assert_eq!(
1040            c(&[0, 1, 2, 1, 0]).get_simplified_mapping(),
1041            vec![0, 1, 2, 3, 4]
1042        );
1043        assert_eq!(c(&[0, 1, 2, 1, 1]).get_simplified_mapping(), vec![0, 3, 2]);
1044        assert_eq!(
1045            c(&[0, 1, 2, 1, 2]).get_simplified_mapping(),
1046            vec![0, 1, 2, 3, 4]
1047        );
1048        assert_eq!(
1049            c(&[0, 1, 2, 1, 3]).get_simplified_mapping(),
1050            vec![0, 1, 2, 3, 4]
1051        );
1052        assert_eq!(c(&[0, 1, 2, 2, 0]).get_simplified_mapping(), vec![0, 1, 4]);
1053        assert_eq!(c(&[0, 1, 2, 2, 1]).get_simplified_mapping(), vec![0]);
1054        assert_eq!(c(&[0, 1, 2, 2, 2]).get_simplified_mapping(), vec![0, 1, 4]);
1055        assert_eq!(c(&[0, 1, 2, 2, 3]).get_simplified_mapping(), vec![0, 1, 4]);
1056        assert_eq!(
1057            c(&[0, 1, 2, 3, 0]).get_simplified_mapping(),
1058            vec![0, 1, 2, 3, 4]
1059        );
1060        assert_eq!(c(&[0, 1, 2, 3, 1]).get_simplified_mapping(), vec![0, 3, 2]);
1061        assert_eq!(
1062            c(&[0, 1, 2, 3, 2]).get_simplified_mapping(),
1063            vec![0, 1, 2, 3, 4]
1064        );
1065        assert_eq!(
1066            c(&[0, 1, 2, 3, 4, 5, 1]).get_simplified_mapping(),
1067            vec![0, 3, 4, 5, 2]
1068        );
1069        assert_eq!(
1070            c(&[0, 1, 2, 3, 4]).get_simplified_mapping(),
1071            vec![0, 1, 2, 3, 4]
1072        );
1073        assert_eq!(c(&[2, 0, 3, 1, 1]).get_simplified_mapping(), vec![0, 1, 2]);
1074    }
1075
1076    #[test]
1077    fn test_simplify() {
1078        // 1-way merge
1079        assert_eq!(c(&[0]).simplify(), c(&[0]));
1080        // 3-way merge
1081        assert_eq!(c(&[0, 0, 0]).simplify(), c(&[0]));
1082        assert_eq!(c(&[0, 0, 1]).simplify(), c(&[1]));
1083        assert_eq!(c(&[1, 0, 0]).simplify(), c(&[1]));
1084        assert_eq!(c(&[1, 0, 1]).simplify(), c(&[1, 0, 1]));
1085        assert_eq!(c(&[1, 0, 2]).simplify(), c(&[1, 0, 2]));
1086        // 5-way merge
1087        assert_eq!(c(&[0, 0, 0, 0, 0]).simplify(), c(&[0]));
1088        assert_eq!(c(&[0, 0, 0, 0, 1]).simplify(), c(&[1]));
1089        assert_eq!(c(&[0, 0, 0, 1, 0]).simplify(), c(&[0, 1, 0]));
1090        assert_eq!(c(&[0, 0, 0, 1, 1]).simplify(), c(&[0]));
1091        assert_eq!(c(&[0, 0, 0, 1, 2]).simplify(), c(&[0, 1, 2]));
1092        assert_eq!(c(&[0, 0, 1, 0, 0]).simplify(), c(&[1]));
1093        assert_eq!(c(&[0, 0, 1, 0, 1]).simplify(), c(&[1, 0, 1]));
1094        assert_eq!(c(&[0, 0, 1, 0, 2]).simplify(), c(&[1, 0, 2]));
1095        assert_eq!(c(&[0, 0, 1, 1, 0]).simplify(), c(&[0]));
1096        assert_eq!(c(&[0, 0, 1, 1, 1]).simplify(), c(&[1]));
1097        assert_eq!(c(&[0, 0, 1, 1, 2]).simplify(), c(&[2]));
1098        assert_eq!(c(&[0, 0, 2, 1, 0]).simplify(), c(&[2, 1, 0]));
1099        assert_eq!(c(&[0, 0, 2, 1, 1]).simplify(), c(&[2]));
1100        assert_eq!(c(&[0, 0, 2, 1, 2]).simplify(), c(&[2, 1, 2]));
1101        assert_eq!(c(&[0, 0, 2, 1, 3]).simplify(), c(&[2, 1, 3]));
1102        assert_eq!(c(&[0, 1, 0, 0, 0]).simplify(), c(&[0, 1, 0]));
1103        assert_eq!(c(&[0, 1, 0, 0, 1]).simplify(), c(&[0]));
1104        assert_eq!(c(&[0, 1, 0, 0, 2]).simplify(), c(&[2, 1, 0]));
1105        assert_eq!(c(&[0, 1, 0, 1, 0]).simplify(), c(&[0, 1, 0, 1, 0]));
1106        assert_eq!(c(&[0, 1, 0, 1, 1]).simplify(), c(&[0, 1, 0]));
1107        assert_eq!(c(&[0, 1, 0, 1, 2]).simplify(), c(&[0, 1, 0, 1, 2]));
1108        assert_eq!(c(&[0, 1, 0, 2, 0]).simplify(), c(&[0, 1, 0, 2, 0]));
1109        assert_eq!(c(&[0, 1, 0, 2, 1]).simplify(), c(&[0, 2, 0]));
1110        assert_eq!(c(&[0, 1, 0, 2, 2]).simplify(), c(&[0, 1, 0]));
1111        assert_eq!(c(&[0, 1, 0, 2, 3]).simplify(), c(&[0, 1, 0, 2, 3]));
1112        assert_eq!(c(&[0, 1, 1, 0, 0]).simplify(), c(&[0]));
1113        assert_eq!(c(&[0, 1, 1, 0, 1]).simplify(), c(&[1]));
1114        assert_eq!(c(&[0, 1, 1, 0, 2]).simplify(), c(&[2]));
1115        assert_eq!(c(&[0, 1, 1, 1, 0]).simplify(), c(&[0, 1, 0]));
1116        assert_eq!(c(&[0, 1, 1, 1, 1]).simplify(), c(&[0]));
1117        assert_eq!(c(&[0, 1, 1, 1, 2]).simplify(), c(&[0, 1, 2]));
1118        assert_eq!(c(&[0, 1, 1, 2, 0]).simplify(), c(&[0, 2, 0]));
1119        assert_eq!(c(&[0, 1, 1, 2, 1]).simplify(), c(&[0, 2, 1]));
1120        assert_eq!(c(&[0, 1, 1, 2, 2]).simplify(), c(&[0]));
1121        assert_eq!(c(&[0, 1, 1, 2, 3]).simplify(), c(&[0, 2, 3]));
1122        assert_eq!(c(&[0, 1, 2, 0, 0]).simplify(), c(&[0, 1, 2]));
1123        assert_eq!(c(&[0, 1, 2, 0, 1]).simplify(), c(&[2]));
1124        assert_eq!(c(&[0, 1, 2, 0, 2]).simplify(), c(&[2, 1, 2]));
1125        assert_eq!(c(&[0, 1, 2, 0, 3]).simplify(), c(&[3, 1, 2]));
1126        assert_eq!(c(&[0, 1, 2, 1, 0]).simplify(), c(&[0, 1, 2, 1, 0]));
1127        assert_eq!(c(&[0, 1, 2, 1, 1]).simplify(), c(&[0, 1, 2]));
1128        assert_eq!(c(&[0, 1, 2, 1, 2]).simplify(), c(&[0, 1, 2, 1, 2]));
1129        assert_eq!(c(&[0, 1, 2, 1, 3]).simplify(), c(&[0, 1, 2, 1, 3]));
1130        assert_eq!(c(&[0, 1, 2, 2, 0]).simplify(), c(&[0, 1, 0]));
1131        assert_eq!(c(&[0, 1, 2, 2, 1]).simplify(), c(&[0]));
1132        assert_eq!(c(&[0, 1, 2, 2, 2]).simplify(), c(&[0, 1, 2]));
1133        assert_eq!(c(&[0, 1, 2, 2, 3]).simplify(), c(&[0, 1, 3]));
1134        assert_eq!(c(&[0, 1, 2, 3, 0]).simplify(), c(&[0, 1, 2, 3, 0]));
1135        assert_eq!(c(&[0, 1, 2, 3, 1]).simplify(), c(&[0, 3, 2]));
1136        assert_eq!(c(&[0, 1, 2, 3, 2]).simplify(), c(&[0, 1, 2, 3, 2]));
1137        assert_eq!(c(&[0, 1, 2, 3, 3]).simplify(), c(&[0, 1, 2]));
1138        assert_eq!(c(&[0, 1, 2, 3, 4]).simplify(), c(&[0, 1, 2, 3, 4]));
1139        assert_eq!(c(&[0, 1, 2, 3, 4, 5, 1]).simplify(), c(&[0, 3, 4, 5, 2]));
1140    }
1141
1142    #[test]
1143    fn test_update_from_simplified() {
1144        // 1-way merge
1145        assert_eq!(c(&[0]).update_from_simplified(c(&[1])), c(&[1]));
1146        // 3-way merge
1147        assert_eq!(c(&[0, 0, 0]).update_from_simplified(c(&[1])), c(&[0, 0, 1]));
1148        assert_eq!(c(&[1, 0, 0]).update_from_simplified(c(&[2])), c(&[2, 0, 0]));
1149        assert_eq!(
1150            c(&[1, 0, 2]).update_from_simplified(c(&[2, 1, 3])),
1151            c(&[2, 1, 3])
1152        );
1153        // 5-way merge
1154        assert_eq!(
1155            c(&[0, 0, 0, 0, 0]).update_from_simplified(c(&[1])),
1156            c(&[0, 0, 0, 0, 1])
1157        );
1158        assert_eq!(
1159            c(&[0, 0, 0, 1, 0]).update_from_simplified(c(&[2, 3, 1])),
1160            c(&[0, 0, 2, 3, 1])
1161        );
1162        assert_eq!(
1163            c(&[0, 1, 0, 0, 0]).update_from_simplified(c(&[2, 3, 1])),
1164            c(&[0, 3, 1, 0, 2])
1165        );
1166        assert_eq!(
1167            c(&[2, 0, 3, 1, 4]).update_from_simplified(c(&[3, 1, 4, 2, 5])),
1168            c(&[3, 1, 4, 2, 5])
1169        );
1170
1171        assert_eq!(c(&[0, 0, 3, 1, 3, 2, 4]).simplify(), c(&[3, 1, 3, 2, 4]));
1172        // Check that the `3`s are replaced correctly and that `4` ends up in the
1173        // correct position.
1174        assert_eq!(
1175            c(&[0, 0, 3, 1, 3, 2, 4]).update_from_simplified(c(&[10, 1, 11, 2, 4])),
1176            c(&[0, 0, 10, 1, 11, 2, 4])
1177        );
1178    }
1179
1180    #[test]
1181    fn test_merge_invariants() {
1182        fn check_invariants(terms: &[u32]) {
1183            let merge = Merge::from_vec(terms.to_vec());
1184            // `simplify()` is idempotent
1185            assert_eq!(
1186                merge.simplify().simplify(),
1187                merge.simplify(),
1188                "simplify() not idempotent for {merge:?}"
1189            );
1190            // `resolve_trivial()` is unaffected by `simplify()`
1191            assert_eq!(
1192                merge.simplify().resolve_trivial(SameChange::Accept),
1193                merge.resolve_trivial(SameChange::Accept),
1194                "simplify() changed result of resolve_trivial() for {merge:?}"
1195            );
1196        }
1197        // 1-way merge
1198        check_invariants(&[0]);
1199        for i in 0..=1 {
1200            for j in 0..=i + 1 {
1201                // 3-way merge
1202                check_invariants(&[i, 0, j]);
1203                for k in 0..=j + 1 {
1204                    for l in 0..=k + 1 {
1205                        // 5-way merge
1206                        check_invariants(&[0, i, j, k, l]);
1207                    }
1208                }
1209            }
1210        }
1211    }
1212
1213    #[test]
1214    fn test_swap_remove() {
1215        let mut x = c(&[0, 1, 2, 3, 4, 5, 6]);
1216        assert_eq!(x.swap_remove(0, 1), (1, 2));
1217        assert_eq!(x, c(&[0, 5, 6, 3, 4]));
1218        assert_eq!(x.swap_remove(1, 0), (3, 0));
1219        assert_eq!(x, c(&[4, 5, 6]));
1220        assert_eq!(x.swap_remove(0, 1), (5, 6));
1221        assert_eq!(x, c(&[4]));
1222    }
1223
1224    #[test]
1225    fn test_pad_to() {
1226        let mut x = c(&[1]);
1227        x.pad_to(3, &2);
1228        assert_eq!(x, c(&[1, 2, 2, 2, 2]));
1229        // No change if the requested size is smaller
1230        x.pad_to(1, &3);
1231        assert_eq!(x, c(&[1, 2, 2, 2, 2]));
1232    }
1233
1234    #[test]
1235    fn test_iter() {
1236        // 1-way merge
1237        assert_eq!(c(&[1]).iter().collect_vec(), vec![&1]);
1238        // 5-way merge
1239        assert_eq!(
1240            c(&[1, 2, 3, 4, 5]).iter().collect_vec(),
1241            vec![&1, &2, &3, &4, &5]
1242        );
1243    }
1244
1245    #[test]
1246    fn test_from_iter() {
1247        // 1-way merge
1248        assert_eq!(MergeBuilder::from_iter([1]).build(), c(&[1]));
1249        // 5-way merge
1250        assert_eq!(
1251            MergeBuilder::from_iter([1, 2, 3, 4, 5]).build(),
1252            c(&[1, 2, 3, 4, 5])
1253        );
1254    }
1255
1256    #[test]
1257    #[should_panic]
1258    fn test_from_iter_empty() {
1259        MergeBuilder::from_iter([1; 0]).build();
1260    }
1261
1262    #[test]
1263    #[should_panic]
1264    fn test_from_iter_even() {
1265        MergeBuilder::from_iter([1, 2]).build();
1266    }
1267
1268    #[test]
1269    fn test_extend() {
1270        // 1-way merge
1271        let mut builder: MergeBuilder<i32> = Default::default();
1272        builder.extend([1]);
1273        assert_eq!(builder.build(), c(&[1]));
1274        // 5-way merge
1275        let mut builder: MergeBuilder<i32> = Default::default();
1276        builder.extend([1, 2]);
1277        builder.extend([3, 4, 5]);
1278        assert_eq!(builder.build(), c(&[1, 2, 3, 4, 5]));
1279    }
1280
1281    #[test]
1282    fn test_map() {
1283        fn increment(i: &i32) -> i32 {
1284            i + 1
1285        }
1286        // 1-way merge
1287        assert_eq!(c(&[1]).map(increment), c(&[2]));
1288        // 3-way merge
1289        assert_eq!(c(&[1, 3, 5]).map(increment), c(&[2, 4, 6]));
1290    }
1291
1292    #[test]
1293    fn test_try_map() {
1294        fn sqrt(i: &i32) -> Result<i32, ()> {
1295            if *i >= 0 {
1296                Ok((*i as f64).sqrt() as i32)
1297            } else {
1298                Err(())
1299            }
1300        }
1301        // 1-way merge
1302        assert_eq!(c(&[1]).try_map(sqrt), Ok(c(&[1])));
1303        assert_eq!(c(&[-1]).try_map(sqrt), Err(()));
1304        // 3-way merge
1305        assert_eq!(c(&[1, 4, 9]).try_map(sqrt), Ok(c(&[1, 2, 3])));
1306        assert_eq!(c(&[-1, 4, 9]).try_map(sqrt), Err(()));
1307        assert_eq!(c(&[1, -4, 9]).try_map(sqrt), Err(()));
1308    }
1309
1310    #[test]
1311    fn test_flatten() {
1312        // 1-way merge of 1-way merge
1313        assert_eq!(c(&[c(&[0])]).flatten(), c(&[0]));
1314        // 1-way merge of 3-way merge
1315        assert_eq!(c(&[c(&[0, 1, 2])]).flatten(), c(&[0, 1, 2]));
1316        // 3-way merge of 1-way merges
1317        assert_eq!(c(&[c(&[0]), c(&[1]), c(&[2])]).flatten(), c(&[0, 1, 2]));
1318        // 3-way merge of 3-way merges
1319        assert_eq!(
1320            c(&[c(&[0, 1, 2]), c(&[3, 4, 5]), c(&[6, 7, 8])]).flatten(),
1321            c(&[0, 1, 2, 5, 4, 3, 6, 7, 8])
1322        );
1323    }
1324}