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