about summary refs log tree commit diff
path: root/third_party/immer/immer/detail/rbts/operations.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/immer/immer/detail/rbts/operations.hpp')
-rw-r--r--third_party/immer/immer/detail/rbts/operations.hpp2461
1 files changed, 0 insertions, 2461 deletions
diff --git a/third_party/immer/immer/detail/rbts/operations.hpp b/third_party/immer/immer/detail/rbts/operations.hpp
deleted file mode 100644
index ff703e892b..0000000000
--- a/third_party/immer/immer/detail/rbts/operations.hpp
+++ /dev/null
@@ -1,2461 +0,0 @@
-//
-// immer: immutable data structures for C++
-// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
-//
-// This software is distributed under the Boost Software License, Version 1.0.
-// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
-//
-
-#pragma once
-
-#include <algorithm>
-#include <memory>
-#include <numeric>
-#include <utility>
-
-#include <immer/config.hpp>
-#include <immer/detail/rbts/position.hpp>
-#include <immer/detail/rbts/visitor.hpp>
-#include <immer/detail/util.hpp>
-#include <immer/heap/tags.hpp>
-
-namespace immer {
-namespace detail {
-namespace rbts {
-
-template <typename T>
-struct array_for_visitor : visitor_base<array_for_visitor<T>>
-{
-    using this_t = array_for_visitor;
-
-    template <typename PosT>
-    static T* visit_inner(PosT&& pos, size_t idx)
-    {
-        return pos.descend(this_t{}, idx);
-    }
-
-    template <typename PosT>
-    static T* visit_leaf(PosT&& pos, size_t)
-    {
-        return pos.node()->leaf();
-    }
-};
-
-template <typename T>
-struct region_for_visitor : visitor_base<region_for_visitor<T>>
-{
-    using this_t   = region_for_visitor;
-    using result_t = std::tuple<T*, size_t, size_t>;
-
-    template <typename PosT>
-    static result_t visit_inner(PosT&& pos, size_t idx)
-    {
-        return pos.towards(this_t{}, idx);
-    }
-
-    template <typename PosT>
-    static result_t visit_leaf(PosT&& pos, size_t idx)
-    {
-        return std::make_tuple(pos.node()->leaf(), pos.index(idx), pos.count());
-    }
-};
-
-template <typename T>
-struct get_visitor : visitor_base<get_visitor<T>>
-{
-    using this_t = get_visitor;
-
-    template <typename PosT>
-    static const T& visit_inner(PosT&& pos, size_t idx)
-    {
-        return pos.descend(this_t{}, idx);
-    }
-
-    template <typename PosT>
-    static const T& visit_leaf(PosT&& pos, size_t idx)
-    {
-        return pos.node()->leaf()[pos.index(idx)];
-    }
-};
-
-struct for_each_chunk_visitor : visitor_base<for_each_chunk_visitor>
-{
-    using this_t = for_each_chunk_visitor;
-
-    template <typename Pos, typename Fn>
-    static void visit_inner(Pos&& pos, Fn&& fn)
-    {
-        pos.each(this_t{}, fn);
-    }
-
-    template <typename Pos, typename Fn>
-    static void visit_leaf(Pos&& pos, Fn&& fn)
-    {
-        auto data = pos.node()->leaf();
-        fn(data, data + pos.count());
-    }
-};
-
-struct for_each_chunk_p_visitor : visitor_base<for_each_chunk_p_visitor>
-{
-    using this_t = for_each_chunk_p_visitor;
-
-    template <typename Pos, typename Fn>
-    static bool visit_inner(Pos&& pos, Fn&& fn)
-    {
-        return pos.each_pred(this_t{}, fn);
-    }
-
-    template <typename Pos, typename Fn>
-    static bool visit_leaf(Pos&& pos, Fn&& fn)
-    {
-        auto data = pos.node()->leaf();
-        return fn(data, data + pos.count());
-    }
-};
-
-struct for_each_chunk_left_visitor : visitor_base<for_each_chunk_left_visitor>
-{
-    using this_t = for_each_chunk_left_visitor;
-
-    template <typename Pos, typename Fn>
-    static void visit_inner(Pos&& pos, size_t last, Fn&& fn)
-    {
-        auto l = pos.index(last);
-        pos.each_left(for_each_chunk_visitor{}, l, fn);
-        pos.towards_oh(this_t{}, last, l, fn);
-    }
-
-    template <typename Pos, typename Fn>
-    static void visit_leaf(Pos&& pos, size_t last, Fn&& fn)
-    {
-        auto data = pos.node()->leaf();
-        auto l    = pos.index(last);
-        fn(data, data + l + 1);
-    }
-};
-
-struct for_each_chunk_right_visitor : visitor_base<for_each_chunk_right_visitor>
-{
-    using this_t = for_each_chunk_right_visitor;
-
-    template <typename Pos, typename Fn>
-    static void visit_inner(Pos&& pos, size_t first, Fn&& fn)
-    {
-        auto f = pos.index(first);
-        pos.towards_oh(this_t{}, first, f, fn);
-        pos.each_right(for_each_chunk_visitor{}, f + 1, fn);
-    }
-
-    template <typename Pos, typename Fn>
-    static void visit_leaf(Pos&& pos, size_t first, Fn&& fn)
-    {
-        auto data = pos.node()->leaf();
-        auto f    = pos.index(first);
-        fn(data + f, data + pos.count());
-    }
-};
-
-struct for_each_chunk_i_visitor : visitor_base<for_each_chunk_i_visitor>
-{
-    using this_t = for_each_chunk_i_visitor;
-
-    template <typename Pos, typename Fn>
-    static void visit_relaxed(Pos&& pos, size_t first, size_t last, Fn&& fn)
-    {
-        // we are going towards *two* indices, so we need to do the
-        // relaxed as a special case to correct the second index
-        if (first < last) {
-            auto f = pos.index(first);
-            auto l = pos.index(last - 1);
-            if (f == l) {
-                auto sbh = pos.size_before(f);
-                pos.towards_oh_sbh(this_t{}, first, f, sbh, last - sbh, fn);
-            } else {
-                assert(f < l);
-                pos.towards_oh(for_each_chunk_right_visitor{}, first, f, fn);
-                pos.each_i(for_each_chunk_visitor{}, f + 1, l, fn);
-                pos.towards_oh(for_each_chunk_left_visitor{}, last - 1, l, fn);
-            }
-        }
-    }
-
-    template <typename Pos, typename Fn>
-    static void visit_regular(Pos&& pos, size_t first, size_t last, Fn&& fn)
-    {
-        if (first < last) {
-            auto f = pos.index(first);
-            auto l = pos.index(last - 1);
-            if (f == l)
-                pos.towards_oh(this_t{}, first, f, last, fn);
-            else {
-                assert(f < l);
-                pos.towards_oh(for_each_chunk_right_visitor{}, first, f, fn);
-                pos.each_i(for_each_chunk_visitor{}, f + 1, l, fn);
-                pos.towards_oh(for_each_chunk_left_visitor{}, last - 1, l, fn);
-            }
-        }
-    }
-
-    template <typename Pos, typename Fn>
-    static void visit_leaf(Pos&& pos, size_t first, size_t last, Fn&& fn)
-    {
-        auto data = pos.node()->leaf();
-        if (first < last) {
-            auto f = pos.index(first);
-            auto l = pos.index(last - 1);
-            fn(data + f, data + l + 1);
-        }
-    }
-};
-
-struct for_each_chunk_p_left_visitor
-    : visitor_base<for_each_chunk_p_left_visitor>
-{
-    using this_t = for_each_chunk_p_left_visitor;
-
-    template <typename Pos, typename Fn>
-    static bool visit_inner(Pos&& pos, size_t last, Fn&& fn)
-    {
-        auto l = pos.index(last);
-        return pos.each_pred_left(for_each_chunk_p_visitor{}, l, fn) &&
-               pos.towards_oh(this_t{}, last, l, fn);
-    }
-
-    template <typename Pos, typename Fn>
-    static bool visit_leaf(Pos&& pos, size_t last, Fn&& fn)
-    {
-        auto data = pos.node()->leaf();
-        auto l    = pos.index(last);
-        return fn(data, data + l + 1);
-    }
-};
-
-struct for_each_chunk_p_right_visitor
-    : visitor_base<for_each_chunk_p_right_visitor>
-{
-    using this_t = for_each_chunk_p_right_visitor;
-
-    template <typename Pos, typename Fn>
-    static bool visit_inner(Pos&& pos, size_t first, Fn&& fn)
-    {
-        auto f = pos.index(first);
-        return pos.towards_oh(this_t{}, first, f, fn) &&
-               pos.each_pred_right(for_each_chunk_p_visitor{}, f + 1, fn);
-    }
-
-    template <typename Pos, typename Fn>
-    static bool visit_leaf(Pos&& pos, size_t first, Fn&& fn)
-    {
-        auto data = pos.node()->leaf();
-        auto f    = pos.index(first);
-        return fn(data + f, data + pos.count());
-    }
-};
-
-struct for_each_chunk_p_i_visitor : visitor_base<for_each_chunk_p_i_visitor>
-{
-    using this_t = for_each_chunk_p_i_visitor;
-
-    template <typename Pos, typename Fn>
-    static bool visit_relaxed(Pos&& pos, size_t first, size_t last, Fn&& fn)
-    {
-        // we are going towards *two* indices, so we need to do the
-        // relaxed as a special case to correct the second index
-        if (first < last) {
-            auto f = pos.index(first);
-            auto l = pos.index(last - 1);
-            if (f == l) {
-                auto sbh = pos.size_before(f);
-                return pos.towards_oh_sbh(
-                    this_t{}, first, f, sbh, last - sbh, fn);
-            } else {
-                assert(f < l);
-                return pos.towards_oh(
-                           for_each_chunk_p_right_visitor{}, first, f, fn) &&
-                       pos.each_pred_i(
-                           for_each_chunk_p_visitor{}, f + 1, l, fn) &&
-                       pos.towards_oh(
-                           for_each_chunk_p_left_visitor{}, last - 1, l, fn);
-            }
-        }
-        return true;
-    }
-
-    template <typename Pos, typename Fn>
-    static bool visit_regular(Pos&& pos, size_t first, size_t last, Fn&& fn)
-    {
-        if (first < last) {
-            auto f = pos.index(first);
-            auto l = pos.index(last - 1);
-            if (f == l)
-                return pos.towards_oh(this_t{}, first, f, last, fn);
-            else {
-                assert(f < l);
-                return pos.towards_oh(
-                           for_each_chunk_p_right_visitor{}, first, f, fn) &&
-                       pos.each_pred_i(
-                           for_each_chunk_p_visitor{}, f + 1, l, fn) &&
-                       pos.towards_oh(
-                           for_each_chunk_p_left_visitor{}, last - 1, l, fn);
-            }
-        }
-        return true;
-    }
-
-    template <typename Pos, typename Fn>
-    static bool visit_leaf(Pos&& pos, size_t first, size_t last, Fn&& fn)
-    {
-        auto data = pos.node()->leaf();
-        if (first < last) {
-            auto f = pos.index(first);
-            auto l = pos.index(last - 1);
-            return fn(data + f, data + l + 1);
-        }
-        return true;
-    }
-};
-
-struct equals_visitor : visitor_base<equals_visitor>
-{
-    using this_t = equals_visitor;
-
-    struct this_aux_t : visitor_base<this_aux_t>
-    {
-        template <typename PosR, typename PosL, typename Iter>
-        static bool visit_inner(
-            PosR&& posr, count_t i, PosL&& posl, Iter&& first, size_t idx)
-        {
-            return posl.nth_sub(i, this_t{}, posr, first, idx);
-        }
-
-        template <typename PosR, typename PosL, typename Iter>
-        static bool visit_leaf(
-            PosR&& posr, count_t i, PosL&& posl, Iter&& first, size_t idx)
-        {
-            return posl.nth_sub_leaf(i, this_t{}, posr, first, idx);
-        }
-    };
-
-    struct rrb : visitor_base<rrb>
-    {
-        template <typename PosR, typename Iter, typename Node>
-        static bool visit_node(PosR&& posr,
-                               Iter&& first,
-                               Node* rootl,
-                               shift_t shiftl,
-                               size_t sizel)
-        {
-            assert(shiftl <= posr.shift());
-            return shiftl == posr.shift()
-                       ? visit_maybe_relaxed_sub(rootl,
-                                                 shiftl,
-                                                 sizel,
-                                                 this_t{},
-                                                 posr,
-                                                 first,
-                                                 size_t{})
-                       : posr.first_sub_inner(
-                             rrb{}, first, rootl, shiftl, sizel);
-        }
-    };
-
-    template <typename Iter>
-    static auto equal_chunk_p(Iter&& iter)
-    {
-        return [iter](auto f, auto e) mutable {
-            if (f == &*iter) {
-                iter += e - f;
-                return true;
-            }
-            for (; f != e; ++f, ++iter)
-                if (*f != *iter)
-                    return false;
-            return true;
-        };
-    }
-
-    template <typename PosL, typename PosR, typename Iter>
-    static bool
-    visit_relaxed(PosL&& posl, PosR&& posr, Iter&& first, size_t idx)
-    {
-        auto nl = posl.node();
-        auto nr = posr.node();
-        if (nl == nr)
-            return true;
-        auto cl = posl.count();
-        auto cr = posr.count();
-        assert(cr > 0);
-        auto sbr = size_t{};
-        auto i   = count_t{};
-        auto j   = count_t{};
-        for (; i < cl; ++i) {
-            auto sbl = posl.size_before(i);
-            for (; j + 1 < cr && (sbr = posr.size_before(j)) < sbl; ++j)
-                ;
-            auto res =
-                sbl == sbr
-                    ? posr.nth_sub(j, this_aux_t{}, i, posl, first, idx + sbl)
-                    : posl.nth_sub(i,
-                                   for_each_chunk_p_visitor{},
-                                   this_t::equal_chunk_p(first + (idx + sbl)));
-            if (!res)
-                return false;
-        }
-        return true;
-    }
-
-    template <typename PosL, typename PosR, typename Iter>
-    static std::enable_if_t<is_relaxed_v<PosR>, bool>
-    visit_regular(PosL&& posl, PosR&& posr, Iter&& first, size_t idx)
-    {
-        return this_t::visit_relaxed(posl, posr, first, idx);
-    }
-
-    template <typename PosL, typename PosR, typename Iter>
-    static std::enable_if_t<!is_relaxed_v<PosR>, bool>
-    visit_regular(PosL&& posl, PosR&& posr, Iter&& first, size_t idx)
-    {
-        return posl.count() >= posr.count()
-                   ? this_t::visit_regular(posl, posr.node())
-                   : this_t::visit_regular(posr, posl.node());
-    }
-
-    template <typename PosL, typename PosR, typename Iter>
-    static bool visit_leaf(PosL&& posl, PosR&& posr, Iter&& first, size_t idx)
-    {
-        if (posl.node() == posr.node())
-            return true;
-        auto cl = posl.count();
-        auto cr = posr.count();
-        auto mp = std::min(cl, cr);
-        return std::equal(posl.node()->leaf(),
-                          posl.node()->leaf() + mp,
-                          posr.node()->leaf()) &&
-               std::equal(posl.node()->leaf() + mp,
-                          posl.node()->leaf() + posl.count(),
-                          first + (idx + mp));
-    }
-
-    template <typename Pos, typename NodeT>
-    static bool visit_regular(Pos&& pos, NodeT* other)
-    {
-        auto node = pos.node();
-        return node == other || pos.each_pred_zip(this_t{}, other);
-    }
-
-    template <typename Pos, typename NodeT>
-    static bool visit_leaf(Pos&& pos, NodeT* other)
-    {
-        auto node = pos.node();
-        return node == other || std::equal(node->leaf(),
-                                           node->leaf() + pos.count(),
-                                           other->leaf());
-    }
-};
-
-template <typename NodeT>
-struct update_visitor : visitor_base<update_visitor<NodeT>>
-{
-    using node_t = NodeT;
-    using this_t = update_visitor;
-
-    template <typename Pos, typename Fn>
-    static node_t* visit_relaxed(Pos&& pos, size_t idx, Fn&& fn)
-    {
-        auto offset = pos.index(idx);
-        auto count  = pos.count();
-        auto node   = node_t::make_inner_sr_n(count, pos.relaxed());
-        try {
-            auto child = pos.towards_oh(this_t{}, idx, offset, fn);
-            node_t::do_copy_inner_sr(node, pos.node(), count);
-            node->inner()[offset]->dec_unsafe();
-            node->inner()[offset] = child;
-            return node;
-        } catch (...) {
-            node_t::delete_inner_r(node, count);
-            throw;
-        }
-    }
-
-    template <typename Pos, typename Fn>
-    static node_t* visit_regular(Pos&& pos, size_t idx, Fn&& fn)
-    {
-        auto offset = pos.index(idx);
-        auto count  = pos.count();
-        auto node   = node_t::make_inner_n(count);
-        try {
-            auto child = pos.towards_oh_ch(this_t{}, idx, offset, count, fn);
-            node_t::do_copy_inner(node, pos.node(), count);
-            node->inner()[offset]->dec_unsafe();
-            node->inner()[offset] = child;
-            return node;
-        } catch (...) {
-            node_t::delete_inner(node, count);
-            throw;
-        }
-    }
-
-    template <typename Pos, typename Fn>
-    static node_t* visit_leaf(Pos&& pos, size_t idx, Fn&& fn)
-    {
-        auto offset = pos.index(idx);
-        auto node   = node_t::copy_leaf(pos.node(), pos.count());
-        try {
-            node->leaf()[offset] =
-                std::forward<Fn>(fn)(std::move(node->leaf()[offset]));
-            return node;
-        } catch (...) {
-            node_t::delete_leaf(node, pos.count());
-            throw;
-        }
-    }
-};
-
-struct dec_visitor : visitor_base<dec_visitor>
-{
-    using this_t = dec_visitor;
-
-    template <typename Pos>
-    static void visit_relaxed(Pos&& p)
-    {
-        using node_t = node_type<Pos>;
-        auto node    = p.node();
-        if (node->dec()) {
-            p.each(this_t{});
-            node_t::delete_inner_r(node, p.count());
-        }
-    }
-
-    template <typename Pos>
-    static void visit_regular(Pos&& p)
-    {
-        using node_t = node_type<Pos>;
-        auto node    = p.node();
-        if (node->dec()) {
-            p.each(this_t{});
-            node_t::delete_inner(node, p.count());
-        }
-    }
-
-    template <typename Pos>
-    static void visit_leaf(Pos&& p)
-    {
-        using node_t = node_type<Pos>;
-        auto node    = p.node();
-        if (node->dec()) {
-            node_t::delete_leaf(node, p.count());
-        }
-    }
-};
-
-template <typename NodeT>
-void dec_leaf(NodeT* node, count_t n)
-{
-    make_leaf_sub_pos(node, n).visit(dec_visitor{});
-}
-
-template <typename NodeT>
-void dec_inner(NodeT* node, shift_t shift, size_t size)
-{
-    visit_maybe_relaxed_sub(node, shift, size, dec_visitor());
-}
-
-template <typename NodeT>
-void dec_relaxed(NodeT* node, shift_t shift)
-{
-    make_relaxed_pos(node, shift, node->relaxed()).visit(dec_visitor());
-}
-
-template <typename NodeT>
-void dec_regular(NodeT* node, shift_t shift, size_t size)
-{
-    make_regular_pos(node, shift, size).visit(dec_visitor());
-}
-
-template <typename NodeT>
-void dec_empty_regular(NodeT* node)
-{
-    make_empty_regular_pos(node).visit(dec_visitor());
-}
-
-template <typename NodeT>
-struct get_mut_visitor : visitor_base<get_mut_visitor<NodeT>>
-{
-    using node_t  = NodeT;
-    using this_t  = get_mut_visitor;
-    using value_t = typename NodeT::value_t;
-    using edit_t  = typename NodeT::edit_t;
-
-    template <typename Pos>
-    static value_t&
-    visit_relaxed(Pos&& pos, size_t idx, edit_t e, node_t** location)
-    {
-        auto offset = pos.index(idx);
-        auto count  = pos.count();
-        auto node   = pos.node();
-        if (node->can_mutate(e)) {
-            return pos.towards_oh(
-                this_t{}, idx, offset, e, &node->inner()[offset]);
-        } else {
-            auto new_node = node_t::copy_inner_sr_e(e, node, count);
-            try {
-                auto& res = pos.towards_oh(
-                    this_t{}, idx, offset, e, &new_node->inner()[offset]);
-                pos.visit(dec_visitor{});
-                *location = new_node;
-                return res;
-            } catch (...) {
-                dec_relaxed(new_node, pos.shift());
-                throw;
-            }
-        }
-    }
-
-    template <typename Pos>
-    static value_t&
-    visit_regular(Pos&& pos, size_t idx, edit_t e, node_t** location)
-    {
-        assert(pos.node() == *location);
-        auto offset = pos.index(idx);
-        auto count  = pos.count();
-        auto node   = pos.node();
-        if (node->can_mutate(e)) {
-            return pos.towards_oh_ch(
-                this_t{}, idx, offset, count, e, &node->inner()[offset]);
-        } else {
-            auto new_node = node_t::copy_inner_e(e, node, count);
-            try {
-                auto& res = pos.towards_oh_ch(this_t{},
-                                              idx,
-                                              offset,
-                                              count,
-                                              e,
-                                              &new_node->inner()[offset]);
-                pos.visit(dec_visitor{});
-                *location = new_node;
-                return res;
-            } catch (...) {
-                dec_regular(new_node, pos.shift(), pos.size());
-                throw;
-            }
-        }
-    }
-
-    template <typename Pos>
-    static value_t&
-    visit_leaf(Pos&& pos, size_t idx, edit_t e, node_t** location)
-    {
-        assert(pos.node() == *location);
-        auto node = pos.node();
-        if (node->can_mutate(e)) {
-            return node->leaf()[pos.index(idx)];
-        } else {
-            auto new_node = node_t::copy_leaf_e(e, pos.node(), pos.count());
-            pos.visit(dec_visitor{});
-            *location = new_node;
-            return new_node->leaf()[pos.index(idx)];
-        }
-    }
-};
-
-template <typename NodeT, bool Mutating = true>
-struct push_tail_mut_visitor
-    : visitor_base<push_tail_mut_visitor<NodeT, Mutating>>
-{
-    static constexpr auto B  = NodeT::bits;
-    static constexpr auto BL = NodeT::bits_leaf;
-
-    using this_t        = push_tail_mut_visitor;
-    using this_no_mut_t = push_tail_mut_visitor<NodeT, false>;
-    using node_t        = NodeT;
-    using edit_t        = typename NodeT::edit_t;
-
-    template <typename Pos>
-    static node_t* visit_relaxed(Pos&& pos, edit_t e, node_t* tail, count_t ts)
-    {
-        auto node     = pos.node();
-        auto level    = pos.shift();
-        auto idx      = pos.count() - 1;
-        auto children = pos.size(idx);
-        auto new_idx =
-            children == size_t{1} << level || level == BL ? idx + 1 : idx;
-        auto new_child = static_cast<node_t*>(nullptr);
-        auto mutate    = Mutating && node->can_mutate(e);
-
-        if (new_idx >= branches<B>)
-            return nullptr;
-        else if (idx == new_idx) {
-            new_child =
-                mutate ? pos.last_oh_csh(this_t{}, idx, children, e, tail, ts)
-                       : pos.last_oh_csh(
-                             this_no_mut_t{}, idx, children, e, tail, ts);
-            if (!new_child) {
-                if (++new_idx < branches<B>)
-                    new_child = node_t::make_path_e(e, level - B, tail);
-                else
-                    return nullptr;
-            }
-        } else
-            new_child = node_t::make_path_e(e, level - B, tail);
-
-        if (mutate) {
-            auto count             = new_idx + 1;
-            auto relaxed           = node->ensure_mutable_relaxed_n(e, new_idx);
-            node->inner()[new_idx] = new_child;
-            relaxed->d.sizes[new_idx] = pos.size() + ts;
-            relaxed->d.count          = count;
-            return node;
-        } else {
-            try {
-                auto count    = new_idx + 1;
-                auto new_node = node_t::copy_inner_r_e(e, pos.node(), new_idx);
-                auto relaxed  = new_node->relaxed();
-                new_node->inner()[new_idx] = new_child;
-                relaxed->d.sizes[new_idx]  = pos.size() + ts;
-                relaxed->d.count           = count;
-                if (Mutating)
-                    pos.visit(dec_visitor{});
-                return new_node;
-            } catch (...) {
-                auto shift = pos.shift();
-                auto size  = new_idx == idx ? children + ts : ts;
-                if (shift > BL) {
-                    tail->inc();
-                    dec_inner(new_child, shift - B, size);
-                }
-                throw;
-            }
-        }
-    }
-
-    template <typename Pos, typename... Args>
-    static node_t* visit_regular(Pos&& pos, edit_t e, node_t* tail, Args&&...)
-    {
-        assert((pos.size() & mask<BL>) == 0);
-        auto node    = pos.node();
-        auto idx     = pos.index(pos.size() - 1);
-        auto new_idx = pos.index(pos.size() + branches<BL> - 1);
-        auto mutate  = Mutating && node->can_mutate(e);
-        if (mutate) {
-            node->inner()[new_idx] =
-                idx == new_idx ? pos.last_oh(this_t{}, idx, e, tail)
-                               /* otherwise */
-                               : node_t::make_path_e(e, pos.shift() - B, tail);
-            return node;
-        } else {
-            auto new_parent = node_t::make_inner_e(e);
-            try {
-                new_parent->inner()[new_idx] =
-                    idx == new_idx
-                        ? pos.last_oh(this_no_mut_t{}, idx, e, tail)
-                        /* otherwise */
-                        : node_t::make_path_e(e, pos.shift() - B, tail);
-                node_t::do_copy_inner(new_parent, node, new_idx);
-                if (Mutating)
-                    pos.visit(dec_visitor{});
-                return new_parent;
-            } catch (...) {
-                node_t::delete_inner_e(new_parent);
-                throw;
-            }
-        }
-    }
-
-    template <typename Pos, typename... Args>
-    static node_t* visit_leaf(Pos&& pos, edit_t e, node_t* tail, Args&&...)
-    {
-        IMMER_UNREACHABLE;
-    }
-};
-
-template <typename NodeT>
-struct push_tail_visitor : visitor_base<push_tail_visitor<NodeT>>
-{
-    static constexpr auto B  = NodeT::bits;
-    static constexpr auto BL = NodeT::bits_leaf;
-
-    using this_t = push_tail_visitor;
-    using node_t = NodeT;
-
-    template <typename Pos>
-    static node_t* visit_relaxed(Pos&& pos, node_t* tail, count_t ts)
-    {
-        auto level    = pos.shift();
-        auto idx      = pos.count() - 1;
-        auto children = pos.size(idx);
-        auto new_idx =
-            children == size_t{1} << level || level == BL ? idx + 1 : idx;
-        auto new_child = static_cast<node_t*>(nullptr);
-        if (new_idx >= branches<B>)
-            return nullptr;
-        else if (idx == new_idx) {
-            new_child = pos.last_oh_csh(this_t{}, idx, children, tail, ts);
-            if (!new_child) {
-                if (++new_idx < branches<B>)
-                    new_child = node_t::make_path(level - B, tail);
-                else
-                    return nullptr;
-            }
-        } else
-            new_child = node_t::make_path(level - B, tail);
-        try {
-            auto count = new_idx + 1;
-            auto new_parent =
-                node_t::copy_inner_r_n(count, pos.node(), new_idx);
-            auto new_relaxed              = new_parent->relaxed();
-            new_parent->inner()[new_idx]  = new_child;
-            new_relaxed->d.sizes[new_idx] = pos.size() + ts;
-            new_relaxed->d.count          = count;
-            return new_parent;
-        } catch (...) {
-            auto shift = pos.shift();
-            auto size  = new_idx == idx ? children + ts : ts;
-            if (shift > BL) {
-                tail->inc();
-                dec_inner(new_child, shift - B, size);
-            }
-            throw;
-        }
-    }
-
-    template <typename Pos, typename... Args>
-    static node_t* visit_regular(Pos&& pos, node_t* tail, Args&&...)
-    {
-        assert((pos.size() & mask<BL>) == 0);
-        auto idx        = pos.index(pos.size() - 1);
-        auto new_idx    = pos.index(pos.size() + branches<BL> - 1);
-        auto count      = new_idx + 1;
-        auto new_parent = node_t::make_inner_n(count);
-        try {
-            new_parent->inner()[new_idx] =
-                idx == new_idx ? pos.last_oh(this_t{}, idx, tail)
-                               /* otherwise */
-                               : node_t::make_path(pos.shift() - B, tail);
-        } catch (...) {
-            node_t::delete_inner(new_parent, count);
-            throw;
-        }
-        return node_t::do_copy_inner(new_parent, pos.node(), new_idx);
-    }
-
-    template <typename Pos, typename... Args>
-    static node_t* visit_leaf(Pos&& pos, node_t* tail, Args&&...)
-    {
-        IMMER_UNREACHABLE;
-    }
-};
-
-struct dec_right_visitor : visitor_base<dec_right_visitor>
-{
-    using this_t = dec_right_visitor;
-    using dec_t  = dec_visitor;
-
-    template <typename Pos>
-    static void visit_relaxed(Pos&& p, count_t idx)
-    {
-        using node_t = node_type<Pos>;
-        auto node    = p.node();
-        if (node->dec()) {
-            p.each_right(dec_t{}, idx);
-            node_t::delete_inner_r(node, p.count());
-        }
-    }
-
-    template <typename Pos>
-    static void visit_regular(Pos&& p, count_t idx)
-    {
-        using node_t = node_type<Pos>;
-        auto node    = p.node();
-        if (node->dec()) {
-            p.each_right(dec_t{}, idx);
-            node_t::delete_inner(node, p.count());
-        }
-    }
-
-    template <typename Pos>
-    static void visit_leaf(Pos&& p, count_t idx)
-    {
-        IMMER_UNREACHABLE;
-    }
-};
-
-template <typename NodeT, bool Collapse = true, bool Mutating = true>
-struct slice_right_mut_visitor
-    : visitor_base<slice_right_mut_visitor<NodeT, Collapse, Mutating>>
-{
-    using node_t = NodeT;
-    using this_t = slice_right_mut_visitor;
-    using edit_t = typename NodeT::edit_t;
-
-    // returns a new shift, new root, the new tail size and the new tail
-    using result_t             = std::tuple<shift_t, NodeT*, count_t, NodeT*>;
-    using no_collapse_t        = slice_right_mut_visitor<NodeT, false, true>;
-    using no_collapse_no_mut_t = slice_right_mut_visitor<NodeT, false, false>;
-    using no_mut_t = slice_right_mut_visitor<NodeT, Collapse, false>;
-
-    static constexpr auto B  = NodeT::bits;
-    static constexpr auto BL = NodeT::bits_leaf;
-
-    template <typename PosT>
-    static result_t visit_relaxed(PosT&& pos, size_t last, edit_t e)
-    {
-        auto idx    = pos.index(last);
-        auto node   = pos.node();
-        auto mutate = Mutating && node->can_mutate(e);
-        if (Collapse && idx == 0) {
-            auto res = mutate ? pos.towards_oh(this_t{}, last, idx, e)
-                              : pos.towards_oh(no_mut_t{}, last, idx, e);
-            if (Mutating)
-                pos.visit(dec_right_visitor{}, count_t{1});
-            return res;
-        } else {
-            using std::get;
-            auto subs =
-                mutate ? pos.towards_oh(no_collapse_t{}, last, idx, e)
-                       : pos.towards_oh(no_collapse_no_mut_t{}, last, idx, e);
-            auto next = get<1>(subs);
-            auto ts   = get<2>(subs);
-            auto tail = get<3>(subs);
-            try {
-                if (next) {
-                    if (mutate) {
-                        auto nodr = node->ensure_mutable_relaxed_n(e, idx);
-                        pos.each_right(dec_visitor{}, idx + 1);
-                        node->inner()[idx] = next;
-                        nodr->d.sizes[idx] = last + 1 - ts;
-                        nodr->d.count      = idx + 1;
-                        return std::make_tuple(pos.shift(), node, ts, tail);
-                    } else {
-                        auto newn = node_t::copy_inner_r_e(e, node, idx);
-                        auto newr = newn->relaxed();
-                        newn->inner()[idx] = next;
-                        newr->d.sizes[idx] = last + 1 - ts;
-                        newr->d.count      = idx + 1;
-                        if (Mutating)
-                            pos.visit(dec_visitor{});
-                        return std::make_tuple(pos.shift(), newn, ts, tail);
-                    }
-                } else if (idx == 0) {
-                    if (Mutating)
-                        pos.visit(dec_right_visitor{}, count_t{1});
-                    return std::make_tuple(pos.shift(), nullptr, ts, tail);
-                } else if (Collapse && idx == 1 && pos.shift() > BL) {
-                    auto newn = pos.node()->inner()[0];
-                    if (!mutate)
-                        newn->inc();
-                    if (Mutating)
-                        pos.visit(dec_right_visitor{}, count_t{2});
-                    return std::make_tuple(pos.shift() - B, newn, ts, tail);
-                } else {
-                    if (mutate) {
-                        pos.each_right(dec_visitor{}, idx + 1);
-                        node->ensure_mutable_relaxed_n(e, idx)->d.count = idx;
-                        return std::make_tuple(pos.shift(), node, ts, tail);
-                    } else {
-                        auto newn = node_t::copy_inner_r_e(e, node, idx);
-                        if (Mutating)
-                            pos.visit(dec_visitor{});
-                        return std::make_tuple(pos.shift(), newn, ts, tail);
-                    }
-                }
-            } catch (...) {
-                assert(!mutate);
-                assert(!next || pos.shift() > BL);
-                if (next)
-                    dec_inner(next,
-                              pos.shift() - B,
-                              last + 1 - ts - pos.size_before(idx));
-                dec_leaf(tail, ts);
-                throw;
-            }
-        }
-    }
-
-    template <typename PosT>
-    static result_t visit_regular(PosT&& pos, size_t last, edit_t e)
-    {
-        auto idx    = pos.index(last);
-        auto node   = pos.node();
-        auto mutate = Mutating && node->can_mutate(e);
-        if (Collapse && idx == 0) {
-            auto res = mutate ? pos.towards_oh(this_t{}, last, idx, e)
-                              : pos.towards_oh(no_mut_t{}, last, idx, e);
-            if (Mutating)
-                pos.visit(dec_right_visitor{}, count_t{1});
-            return res;
-        } else {
-            using std::get;
-            auto subs =
-                mutate ? pos.towards_oh(no_collapse_t{}, last, idx, e)
-                       : pos.towards_oh(no_collapse_no_mut_t{}, last, idx, e);
-            auto next = get<1>(subs);
-            auto ts   = get<2>(subs);
-            auto tail = get<3>(subs);
-            try {
-                if (next) {
-                    if (mutate) {
-                        node->inner()[idx] = next;
-                        pos.each_right(dec_visitor{}, idx + 1);
-                        return std::make_tuple(pos.shift(), node, ts, tail);
-                    } else {
-                        auto newn          = node_t::copy_inner_e(e, node, idx);
-                        newn->inner()[idx] = next;
-                        if (Mutating)
-                            pos.visit(dec_visitor{});
-                        return std::make_tuple(pos.shift(), newn, ts, tail);
-                    }
-                } else if (idx == 0) {
-                    if (Mutating)
-                        pos.visit(dec_right_visitor{}, count_t{1});
-                    return std::make_tuple(pos.shift(), nullptr, ts, tail);
-                } else if (Collapse && idx == 1 && pos.shift() > BL) {
-                    auto newn = pos.node()->inner()[0];
-                    if (!mutate)
-                        newn->inc();
-                    if (Mutating)
-                        pos.visit(dec_right_visitor{}, count_t{2});
-                    return std::make_tuple(pos.shift() - B, newn, ts, tail);
-                } else {
-                    if (mutate) {
-                        pos.each_right(dec_visitor{}, idx + 1);
-                        return std::make_tuple(pos.shift(), node, ts, tail);
-                    } else {
-                        auto newn = node_t::copy_inner_e(e, node, idx);
-                        if (Mutating)
-                            pos.visit(dec_visitor{});
-                        return std::make_tuple(pos.shift(), newn, ts, tail);
-                    }
-                }
-            } catch (...) {
-                assert(!mutate);
-                assert(!next || pos.shift() > BL);
-                assert(tail);
-                if (next)
-                    dec_regular(next, pos.shift() - B, last + 1 - ts);
-                dec_leaf(tail, ts);
-                throw;
-            }
-        }
-    }
-
-    template <typename PosT>
-    static result_t visit_leaf(PosT&& pos, size_t last, edit_t e)
-    {
-        auto old_tail_size = pos.count();
-        auto new_tail_size = pos.index(last) + 1;
-        auto node          = pos.node();
-        auto mutate        = Mutating && node->can_mutate(e);
-        if (new_tail_size == old_tail_size) {
-            if (!Mutating)
-                node->inc();
-            return std::make_tuple(0, nullptr, new_tail_size, node);
-        } else if (mutate) {
-            destroy_n(node->leaf() + new_tail_size,
-                      old_tail_size - new_tail_size);
-            return std::make_tuple(0, nullptr, new_tail_size, node);
-        } else {
-            auto new_tail = node_t::copy_leaf_e(e, node, new_tail_size);
-            if (Mutating)
-                pos.visit(dec_visitor{});
-            return std::make_tuple(0, nullptr, new_tail_size, new_tail);
-        }
-    }
-};
-
-template <typename NodeT, bool Collapse = true>
-struct slice_right_visitor : visitor_base<slice_right_visitor<NodeT, Collapse>>
-{
-    using node_t = NodeT;
-    using this_t = slice_right_visitor;
-
-    // returns a new shift, new root, the new tail size and the new tail
-    using result_t      = std::tuple<shift_t, NodeT*, count_t, NodeT*>;
-    using no_collapse_t = slice_right_visitor<NodeT, false>;
-
-    static constexpr auto B  = NodeT::bits;
-    static constexpr auto BL = NodeT::bits_leaf;
-
-    template <typename PosT>
-    static result_t visit_relaxed(PosT&& pos, size_t last)
-    {
-        auto idx = pos.index(last);
-        if (Collapse && idx == 0) {
-            return pos.towards_oh(this_t{}, last, idx);
-        } else {
-            using std::get;
-            auto subs = pos.towards_oh(no_collapse_t{}, last, idx);
-            auto next = get<1>(subs);
-            auto ts   = get<2>(subs);
-            auto tail = get<3>(subs);
-            try {
-                if (next) {
-                    auto count = idx + 1;
-                    auto newn  = node_t::copy_inner_r_n(count, pos.node(), idx);
-                    auto newr  = newn->relaxed();
-                    newn->inner()[idx] = next;
-                    newr->d.sizes[idx] = last + 1 - ts;
-                    newr->d.count      = count;
-                    return std::make_tuple(pos.shift(), newn, ts, tail);
-                } else if (idx == 0) {
-                    return std::make_tuple(pos.shift(), nullptr, ts, tail);
-                } else if (Collapse && idx == 1 && pos.shift() > BL) {
-                    auto newn = pos.node()->inner()[0];
-                    return std::make_tuple(
-                        pos.shift() - B, newn->inc(), ts, tail);
-                } else {
-                    auto newn = node_t::copy_inner_r(pos.node(), idx);
-                    return std::make_tuple(pos.shift(), newn, ts, tail);
-                }
-            } catch (...) {
-                assert(!next || pos.shift() > BL);
-                if (next)
-                    dec_inner(next,
-                              pos.shift() - B,
-                              last + 1 - ts - pos.size_before(idx));
-                if (tail)
-                    dec_leaf(tail, ts);
-                throw;
-            }
-        }
-    }
-
-    template <typename PosT>
-    static result_t visit_regular(PosT&& pos, size_t last)
-    {
-        auto idx = pos.index(last);
-        if (Collapse && idx == 0) {
-            return pos.towards_oh(this_t{}, last, idx);
-        } else {
-            using std::get;
-            auto subs = pos.towards_oh(no_collapse_t{}, last, idx);
-            auto next = get<1>(subs);
-            auto ts   = get<2>(subs);
-            auto tail = get<3>(subs);
-            try {
-                if (next) {
-                    auto newn = node_t::copy_inner_n(idx + 1, pos.node(), idx);
-                    newn->inner()[idx] = next;
-                    return std::make_tuple(pos.shift(), newn, ts, tail);
-                } else if (idx == 0) {
-                    return std::make_tuple(pos.shift(), nullptr, ts, tail);
-                } else if (Collapse && idx == 1 && pos.shift() > BL) {
-                    auto newn = pos.node()->inner()[0];
-                    return std::make_tuple(
-                        pos.shift() - B, newn->inc(), ts, tail);
-                } else {
-                    auto newn = node_t::copy_inner_n(idx, pos.node(), idx);
-                    return std::make_tuple(pos.shift(), newn, ts, tail);
-                }
-            } catch (...) {
-                assert(!next || pos.shift() > BL);
-                assert(tail);
-                if (next)
-                    dec_regular(next, pos.shift() - B, last + 1 - ts);
-                dec_leaf(tail, ts);
-                throw;
-            }
-        }
-    }
-
-    template <typename PosT>
-    static result_t visit_leaf(PosT&& pos, size_t last)
-    {
-        auto old_tail_size = pos.count();
-        auto new_tail_size = pos.index(last) + 1;
-        auto new_tail      = new_tail_size == old_tail_size
-                            ? pos.node()->inc()
-                            : node_t::copy_leaf(pos.node(), new_tail_size);
-        return std::make_tuple(0, nullptr, new_tail_size, new_tail);
-    }
-};
-
-struct dec_left_visitor : visitor_base<dec_left_visitor>
-{
-    using this_t = dec_left_visitor;
-    using dec_t  = dec_visitor;
-
-    template <typename Pos>
-    static void visit_relaxed(Pos&& p, count_t idx)
-    {
-        using node_t = node_type<Pos>;
-        auto node    = p.node();
-        if (node->dec()) {
-            p.each_left(dec_t{}, idx);
-            node_t::delete_inner_r(node, p.count());
-        }
-    }
-
-    template <typename Pos>
-    static void visit_regular(Pos&& p, count_t idx)
-    {
-        using node_t = node_type<Pos>;
-        auto node    = p.node();
-        if (node->dec()) {
-            p.each_left(dec_t{}, idx);
-            node_t::delete_inner(node, p.count());
-        }
-    }
-
-    template <typename Pos>
-    static void visit_leaf(Pos&& p, count_t idx)
-    {
-        IMMER_UNREACHABLE;
-    }
-};
-
-template <typename NodeT, bool Collapse = true, bool Mutating = true>
-struct slice_left_mut_visitor
-    : visitor_base<slice_left_mut_visitor<NodeT, Collapse, Mutating>>
-{
-    using node_t    = NodeT;
-    using this_t    = slice_left_mut_visitor;
-    using edit_t    = typename NodeT::edit_t;
-    using value_t   = typename NodeT::value_t;
-    using relaxed_t = typename NodeT::relaxed_t;
-    // returns a new shift and new root
-    using result_t = std::tuple<shift_t, NodeT*>;
-
-    using no_collapse_t        = slice_left_mut_visitor<NodeT, false, true>;
-    using no_collapse_no_mut_t = slice_left_mut_visitor<NodeT, false, false>;
-    using no_mut_t             = slice_left_mut_visitor<NodeT, Collapse, false>;
-
-    static constexpr auto B  = NodeT::bits;
-    static constexpr auto BL = NodeT::bits_leaf;
-
-    template <typename PosT>
-    static result_t visit_relaxed(PosT&& pos, size_t first, edit_t e)
-    {
-        auto idx                = pos.subindex(first);
-        auto count              = pos.count();
-        auto node               = pos.node();
-        auto mutate             = Mutating && node->can_mutate(e);
-        auto left_size          = pos.size_before(idx);
-        auto child_size         = pos.size_sbh(idx, left_size);
-        auto dropped_size       = first;
-        auto child_dropped_size = dropped_size - left_size;
-        if (Collapse && pos.shift() > BL && idx == pos.count() - 1) {
-            auto r = mutate ? pos.towards_sub_oh(this_t{}, first, idx, e)
-                            : pos.towards_sub_oh(no_mut_t{}, first, idx, e);
-            if (Mutating)
-                pos.visit(dec_left_visitor{}, idx);
-            return r;
-        } else {
-            using std::get;
-            auto newn = mutate ? (node->ensure_mutable_relaxed(e), node)
-                               : node_t::make_inner_r_e(e);
-            auto newr           = newn->relaxed();
-            auto newcount       = count - idx;
-            auto new_child_size = child_size - child_dropped_size;
-            try {
-                auto subs =
-                    mutate ? pos.towards_sub_oh(no_collapse_t{}, first, idx, e)
-                           : pos.towards_sub_oh(
-                                 no_collapse_no_mut_t{}, first, idx, e);
-                if (mutate)
-                    pos.each_left(dec_visitor{}, idx);
-                pos.copy_sizes(
-                    idx + 1, newcount - 1, new_child_size, newr->d.sizes + 1);
-                std::uninitialized_copy(node->inner() + idx + 1,
-                                        node->inner() + count,
-                                        newn->inner() + 1);
-                newn->inner()[0] = get<1>(subs);
-                newr->d.sizes[0] = new_child_size;
-                newr->d.count    = newcount;
-                if (!mutate) {
-                    node_t::inc_nodes(newn->inner() + 1, newcount - 1);
-                    if (Mutating)
-                        pos.visit(dec_visitor{});
-                }
-                return std::make_tuple(pos.shift(), newn);
-            } catch (...) {
-                if (!mutate)
-                    node_t::delete_inner_r_e(newn);
-                throw;
-            }
-        }
-    }
-
-    template <typename PosT>
-    static result_t visit_regular(PosT&& pos, size_t first, edit_t e)
-    {
-        auto idx    = pos.subindex(first);
-        auto count  = pos.count();
-        auto node   = pos.node();
-        auto mutate = Mutating
-                      // this is more restrictive than actually needed because
-                      // it causes the algorithm to also avoid mutating the leaf
-                      // in place
-                      && !node_t::embed_relaxed && node->can_mutate(e);
-        auto left_size          = pos.size_before(idx);
-        auto child_size         = pos.size_sbh(idx, left_size);
-        auto dropped_size       = first;
-        auto child_dropped_size = dropped_size - left_size;
-        if (Collapse && pos.shift() > BL && idx == pos.count() - 1) {
-            auto r = mutate ? pos.towards_sub_oh(this_t{}, first, idx, e)
-                            : pos.towards_sub_oh(no_mut_t{}, first, idx, e);
-            if (Mutating)
-                pos.visit(dec_left_visitor{}, idx);
-            return r;
-        } else {
-            using std::get;
-            // if possible, we convert the node to a relaxed one
-            // simply by allocating a `relaxed_t` size table for
-            // it... maybe some of this magic should be moved as a
-            // `node<...>` static method...
-            auto newcount = count - idx;
-            auto newn =
-                mutate ? (node->impl.d.data.inner.relaxed = new (
-                              node_t::heap::allocate(node_t::max_sizeof_relaxed,
-                                                     norefs_tag{})) relaxed_t,
-                          node)
-                       : node_t::make_inner_r_e(e);
-            auto newr = newn->relaxed();
-            try {
-                auto subs =
-                    mutate ? pos.towards_sub_oh(no_collapse_t{}, first, idx, e)
-                           : pos.towards_sub_oh(
-                                 no_collapse_no_mut_t{}, first, idx, e);
-                if (mutate)
-                    pos.each_left(dec_visitor{}, idx);
-                newr->d.sizes[0] = child_size - child_dropped_size;
-                pos.copy_sizes(
-                    idx + 1, newcount - 1, newr->d.sizes[0], newr->d.sizes + 1);
-                newr->d.count    = newcount;
-                newn->inner()[0] = get<1>(subs);
-                std::uninitialized_copy(node->inner() + idx + 1,
-                                        node->inner() + count,
-                                        newn->inner() + 1);
-                if (!mutate) {
-                    node_t::inc_nodes(newn->inner() + 1, newcount - 1);
-                    if (Mutating)
-                        pos.visit(dec_visitor{});
-                }
-                return std::make_tuple(pos.shift(), newn);
-            } catch (...) {
-                if (!mutate)
-                    node_t::delete_inner_r_e(newn);
-                else {
-                    // restore the regular node that we were
-                    // attempting to relax...
-                    node_t::heap::deallocate(node_t::max_sizeof_relaxed,
-                                             node->impl.d.data.inner.relaxed);
-                    node->impl.d.data.inner.relaxed = nullptr;
-                }
-                throw;
-            }
-        }
-    }
-
-    template <typename PosT>
-    static result_t visit_leaf(PosT&& pos, size_t first, edit_t e)
-    {
-        auto node   = pos.node();
-        auto idx    = pos.index(first);
-        auto count  = pos.count();
-        auto mutate = Mutating &&
-                      std::is_nothrow_move_constructible<value_t>::value &&
-                      node->can_mutate(e);
-        if (mutate) {
-            auto data     = node->leaf();
-            auto newcount = count - idx;
-            std::move(data + idx, data + count, data);
-            destroy_n(data + newcount, idx);
-            return std::make_tuple(0, node);
-        } else {
-            auto newn = node_t::copy_leaf_e(e, node, idx, count);
-            if (Mutating)
-                pos.visit(dec_visitor{});
-            return std::make_tuple(0, newn);
-        }
-    }
-};
-
-template <typename NodeT, bool Collapse = true>
-struct slice_left_visitor : visitor_base<slice_left_visitor<NodeT, Collapse>>
-{
-    using node_t = NodeT;
-    using this_t = slice_left_visitor;
-
-    // returns a new shift and new root
-    using result_t      = std::tuple<shift_t, NodeT*>;
-    using no_collapse_t = slice_left_visitor<NodeT, false>;
-
-    static constexpr auto B  = NodeT::bits;
-    static constexpr auto BL = NodeT::bits_leaf;
-
-    template <typename PosT>
-    static result_t visit_inner(PosT&& pos, size_t first)
-    {
-        auto idx                = pos.subindex(first);
-        auto count              = pos.count();
-        auto left_size          = pos.size_before(idx);
-        auto child_size         = pos.size_sbh(idx, left_size);
-        auto dropped_size       = first;
-        auto child_dropped_size = dropped_size - left_size;
-        if (Collapse && pos.shift() > BL && idx == pos.count() - 1) {
-            return pos.towards_sub_oh(this_t{}, first, idx);
-        } else {
-            using std::get;
-            auto n    = pos.node();
-            auto newc = count - idx;
-            auto newn = node_t::make_inner_r_n(newc);
-            try {
-                auto subs     = pos.towards_sub_oh(no_collapse_t{}, first, idx);
-                auto newr     = newn->relaxed();
-                newr->d.count = count - idx;
-                newr->d.sizes[0] = child_size - child_dropped_size;
-                pos.copy_sizes(idx + 1,
-                               newr->d.count - 1,
-                               newr->d.sizes[0],
-                               newr->d.sizes + 1);
-                assert(newr->d.sizes[newr->d.count - 1] ==
-                       pos.size() - dropped_size);
-                newn->inner()[0] = get<1>(subs);
-                std::uninitialized_copy(n->inner() + idx + 1,
-                                        n->inner() + count,
-                                        newn->inner() + 1);
-                node_t::inc_nodes(newn->inner() + 1, newr->d.count - 1);
-                return std::make_tuple(pos.shift(), newn);
-            } catch (...) {
-                node_t::delete_inner_r(newn, newc);
-                throw;
-            }
-        }
-    }
-
-    template <typename PosT>
-    static result_t visit_leaf(PosT&& pos, size_t first)
-    {
-        auto n = node_t::copy_leaf(pos.node(), pos.index(first), pos.count());
-        return std::make_tuple(0, n);
-    }
-};
-
-template <typename Node>
-struct concat_center_pos
-{
-    static constexpr auto B  = Node::bits;
-    static constexpr auto BL = Node::bits_leaf;
-
-    static constexpr count_t max_children = 3;
-
-    using node_t = Node;
-    using edit_t = typename Node::edit_t;
-
-    shift_t shift_ = 0u;
-    count_t count_ = 0u;
-    node_t* nodes_[max_children];
-    size_t sizes_[max_children];
-
-    auto shift() const { return shift_; }
-
-    concat_center_pos(shift_t s, Node* n0, size_t s0)
-        : shift_{s}
-        , count_{1}
-        , nodes_{n0}
-        , sizes_{s0}
-    {}
-
-    concat_center_pos(shift_t s, Node* n0, size_t s0, Node* n1, size_t s1)
-        : shift_{s}
-        , count_{2}
-        , nodes_{n0, n1}
-        , sizes_{s0, s1}
-    {}
-
-    concat_center_pos(shift_t s,
-                      Node* n0,
-                      size_t s0,
-                      Node* n1,
-                      size_t s1,
-                      Node* n2,
-                      size_t s2)
-        : shift_{s}
-        , count_{3}
-        , nodes_{n0, n1, n2}
-        , sizes_{s0, s1, s2}
-    {}
-
-    template <typename Visitor, typename... Args>
-    void each_sub(Visitor v, Args&&... args)
-    {
-        if (shift_ == BL) {
-            for (auto i = count_t{0}; i < count_; ++i)
-                make_leaf_sub_pos(nodes_[i], sizes_[i]).visit(v, args...);
-        } else {
-            for (auto i = count_t{0}; i < count_; ++i)
-                make_relaxed_pos(nodes_[i], shift_ - B, nodes_[i]->relaxed())
-                    .visit(v, args...);
-        }
-    }
-
-    relaxed_pos<Node> realize() &&
-    {
-        if (count_ > 1) {
-            try {
-                auto result = node_t::make_inner_r_n(count_);
-                auto r      = result->relaxed();
-                r->d.count  = count_;
-                std::copy(nodes_, nodes_ + count_, result->inner());
-                std::copy(sizes_, sizes_ + count_, r->d.sizes);
-                return {result, shift_, r};
-            } catch (...) {
-                each_sub(dec_visitor{});
-                throw;
-            }
-        } else {
-            assert(shift_ >= B + BL);
-            return {nodes_[0], shift_ - B, nodes_[0]->relaxed()};
-        }
-    }
-
-    relaxed_pos<Node> realize_e(edit_t e)
-    {
-        if (count_ > 1) {
-            auto result = node_t::make_inner_r_e(e);
-            auto r      = result->relaxed();
-            r->d.count  = count_;
-            std::copy(nodes_, nodes_ + count_, result->inner());
-            std::copy(sizes_, sizes_ + count_, r->d.sizes);
-            return {result, shift_, r};
-        } else {
-            assert(shift_ >= B + BL);
-            return {nodes_[0], shift_ - B, nodes_[0]->relaxed()};
-        }
-    }
-};
-
-template <typename Node>
-struct concat_merger
-{
-    using node_t             = Node;
-    static constexpr auto B  = Node::bits;
-    static constexpr auto BL = Node::bits_leaf;
-
-    using result_t = concat_center_pos<Node>;
-
-    count_t* curr_;
-    count_t n_;
-    result_t result_;
-
-    concat_merger(shift_t shift, count_t* counts, count_t n)
-        : curr_{counts}
-        , n_{n}
-        , result_{
-              shift + B, node_t::make_inner_r_n(std::min(n_, branches<B>)), 0}
-    {}
-
-    node_t* to_        = {};
-    count_t to_offset_ = {};
-    size_t to_size_    = {};
-
-    void add_child(node_t* p, size_t size)
-    {
-        ++curr_;
-        auto parent  = result_.nodes_[result_.count_ - 1];
-        auto relaxed = parent->relaxed();
-        if (relaxed->d.count == branches<B>) {
-            assert(result_.count_ < result_t::max_children);
-            n_ -= branches<B>;
-            parent  = node_t::make_inner_r_n(std::min(n_, branches<B>));
-            relaxed = parent->relaxed();
-            result_.nodes_[result_.count_] = parent;
-            result_.sizes_[result_.count_] = result_.sizes_[result_.count_ - 1];
-            ++result_.count_;
-        }
-        auto idx = relaxed->d.count++;
-        result_.sizes_[result_.count_ - 1] += size;
-        relaxed->d.sizes[idx] = size + (idx ? relaxed->d.sizes[idx - 1] : 0);
-        parent->inner()[idx]  = p;
-    };
-
-    template <typename Pos>
-    void merge_leaf(Pos&& p)
-    {
-        auto from       = p.node();
-        auto from_size  = p.size();
-        auto from_count = p.count();
-        assert(from_size);
-        if (!to_ && *curr_ == from_count) {
-            add_child(from, from_size);
-            from->inc();
-        } else {
-            auto from_offset = count_t{};
-            auto from_data   = from->leaf();
-            do {
-                if (!to_) {
-                    to_        = node_t::make_leaf_n(*curr_);
-                    to_offset_ = 0;
-                }
-                auto data = to_->leaf();
-                auto to_copy =
-                    std::min(from_count - from_offset, *curr_ - to_offset_);
-                std::uninitialized_copy(from_data + from_offset,
-                                        from_data + from_offset + to_copy,
-                                        data + to_offset_);
-                to_offset_ += to_copy;
-                from_offset += to_copy;
-                if (*curr_ == to_offset_) {
-                    add_child(to_, to_offset_);
-                    to_ = nullptr;
-                }
-            } while (from_offset != from_count);
-        }
-    }
-
-    template <typename Pos>
-    void merge_inner(Pos&& p)
-    {
-        auto from       = p.node();
-        auto from_size  = p.size();
-        auto from_count = p.count();
-        assert(from_size);
-        if (!to_ && *curr_ == from_count) {
-            add_child(from, from_size);
-            from->inc();
-        } else {
-            auto from_offset = count_t{};
-            auto from_data   = from->inner();
-            do {
-                if (!to_) {
-                    to_        = node_t::make_inner_r_n(*curr_);
-                    to_offset_ = 0;
-                    to_size_   = 0;
-                }
-                auto data = to_->inner();
-                auto to_copy =
-                    std::min(from_count - from_offset, *curr_ - to_offset_);
-                std::uninitialized_copy(from_data + from_offset,
-                                        from_data + from_offset + to_copy,
-                                        data + to_offset_);
-                node_t::inc_nodes(from_data + from_offset, to_copy);
-                auto sizes = to_->relaxed()->d.sizes;
-                p.copy_sizes(
-                    from_offset, to_copy, to_size_, sizes + to_offset_);
-                to_offset_ += to_copy;
-                from_offset += to_copy;
-                to_size_ = sizes[to_offset_ - 1];
-                if (*curr_ == to_offset_) {
-                    to_->relaxed()->d.count = to_offset_;
-                    add_child(to_, to_size_);
-                    to_ = nullptr;
-                }
-            } while (from_offset != from_count);
-        }
-    }
-
-    concat_center_pos<Node> finish() const
-    {
-        assert(!to_);
-        return result_;
-    }
-
-    void abort()
-    {
-        auto shift = result_.shift_ - B;
-        if (to_) {
-            if (shift == BL)
-                node_t::delete_leaf(to_, to_offset_);
-            else {
-                to_->relaxed()->d.count = to_offset_;
-                dec_relaxed(to_, shift - B);
-            }
-        }
-        result_.each_sub(dec_visitor());
-    }
-};
-
-struct concat_merger_visitor : visitor_base<concat_merger_visitor>
-{
-    using this_t = concat_merger_visitor;
-
-    template <typename Pos, typename Merger>
-    static void visit_inner(Pos&& p, Merger& merger)
-    {
-        merger.merge_inner(p);
-    }
-
-    template <typename Pos, typename Merger>
-    static void visit_leaf(Pos&& p, Merger& merger)
-    {
-        merger.merge_leaf(p);
-    }
-};
-
-struct concat_rebalance_plan_fill_visitor
-    : visitor_base<concat_rebalance_plan_fill_visitor>
-{
-    using this_t = concat_rebalance_plan_fill_visitor;
-
-    template <typename Pos, typename Plan>
-    static void visit_node(Pos&& p, Plan& plan)
-    {
-        auto count = p.count();
-        assert(plan.n < Plan::max_children);
-        plan.counts[plan.n++] = count;
-        plan.total += count;
-    }
-};
-
-template <bits_t B, bits_t BL>
-struct concat_rebalance_plan
-{
-    static constexpr auto max_children = 2 * branches<B> + 1;
-
-    count_t counts[max_children];
-    count_t n     = 0u;
-    count_t total = 0u;
-
-    template <typename LPos, typename CPos, typename RPos>
-    void fill(LPos&& lpos, CPos&& cpos, RPos&& rpos)
-    {
-        assert(n == 0u);
-        assert(total == 0u);
-        using visitor_t = concat_rebalance_plan_fill_visitor;
-        lpos.each_left_sub(visitor_t{}, *this);
-        cpos.each_sub(visitor_t{}, *this);
-        rpos.each_right_sub(visitor_t{}, *this);
-    }
-
-    void shuffle(shift_t shift)
-    {
-        // gcc seems to not really understand this code... :(
-#if !defined(_MSC_VER)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Warray-bounds"
-#endif
-        constexpr count_t rrb_extras    = 2;
-        constexpr count_t rrb_invariant = 1;
-        const auto bits                 = shift == BL ? BL : B;
-        const auto branches             = count_t{1} << bits;
-        const auto optimal              = ((total - 1) >> bits) + 1;
-        count_t i                       = 0;
-        while (n >= optimal + rrb_extras) {
-            // skip ok nodes
-            while (counts[i] > branches - rrb_invariant)
-                i++;
-            // short node, redistribute
-            auto remaining = counts[i];
-            do {
-                auto count = std::min(remaining + counts[i + 1], branches);
-                counts[i]  = count;
-                remaining += counts[i + 1] - count;
-                ++i;
-            } while (remaining > 0);
-            // remove node
-            std::move(counts + i + 1, counts + n, counts + i);
-            --n;
-            --i;
-        }
-#if !defined(_MSC_VER)
-#pragma GCC diagnostic pop
-#endif
-    }
-
-    template <typename LPos, typename CPos, typename RPos>
-    concat_center_pos<node_type<CPos>>
-    merge(LPos&& lpos, CPos&& cpos, RPos&& rpos)
-    {
-        using node_t    = node_type<CPos>;
-        using merger_t  = concat_merger<node_t>;
-        using visitor_t = concat_merger_visitor;
-        auto merger     = merger_t{cpos.shift(), counts, n};
-        try {
-            lpos.each_left_sub(visitor_t{}, merger);
-            cpos.each_sub(visitor_t{}, merger);
-            rpos.each_right_sub(visitor_t{}, merger);
-            cpos.each_sub(dec_visitor{});
-            return merger.finish();
-        } catch (...) {
-            merger.abort();
-            throw;
-        }
-    }
-};
-
-template <typename Node, typename LPos, typename CPos, typename RPos>
-concat_center_pos<Node> concat_rebalance(LPos&& lpos, CPos&& cpos, RPos&& rpos)
-{
-    auto plan = concat_rebalance_plan<Node::bits, Node::bits_leaf>{};
-    plan.fill(lpos, cpos, rpos);
-    plan.shuffle(cpos.shift());
-    try {
-        return plan.merge(lpos, cpos, rpos);
-    } catch (...) {
-        cpos.each_sub(dec_visitor{});
-        throw;
-    }
-}
-
-template <typename Node, typename LPos, typename TPos, typename RPos>
-concat_center_pos<Node> concat_leafs(LPos&& lpos, TPos&& tpos, RPos&& rpos)
-{
-    static_assert(Node::bits >= 2, "");
-    assert(lpos.shift() == tpos.shift());
-    assert(lpos.shift() == rpos.shift());
-    assert(lpos.shift() == 0);
-    if (tpos.count() > 0)
-        return {
-            Node::bits_leaf,
-            lpos.node()->inc(),
-            lpos.count(),
-            tpos.node()->inc(),
-            tpos.count(),
-            rpos.node()->inc(),
-            rpos.count(),
-        };
-    else
-        return {
-            Node::bits_leaf,
-            lpos.node()->inc(),
-            lpos.count(),
-            rpos.node()->inc(),
-            rpos.count(),
-        };
-}
-
-template <typename Node>
-struct concat_left_visitor;
-template <typename Node>
-struct concat_right_visitor;
-template <typename Node>
-struct concat_both_visitor;
-
-template <typename Node, typename LPos, typename TPos, typename RPos>
-concat_center_pos<Node> concat_inners(LPos&& lpos, TPos&& tpos, RPos&& rpos)
-{
-    auto lshift = lpos.shift();
-    auto rshift = rpos.shift();
-    if (lshift > rshift) {
-        auto cpos = lpos.last_sub(concat_left_visitor<Node>{}, tpos, rpos);
-        return concat_rebalance<Node>(lpos, cpos, null_sub_pos{});
-    } else if (lshift < rshift) {
-        auto cpos = rpos.first_sub(concat_right_visitor<Node>{}, lpos, tpos);
-        return concat_rebalance<Node>(null_sub_pos{}, cpos, rpos);
-    } else {
-        assert(lshift == rshift);
-        assert(Node::bits_leaf == 0u || lshift > 0);
-        auto cpos = lpos.last_sub(concat_both_visitor<Node>{}, tpos, rpos);
-        return concat_rebalance<Node>(lpos, cpos, rpos);
-    }
-}
-
-template <typename Node>
-struct concat_left_visitor : visitor_base<concat_left_visitor<Node>>
-{
-    using this_t = concat_left_visitor;
-
-    template <typename LPos, typename TPos, typename RPos>
-    static concat_center_pos<Node>
-    visit_inner(LPos&& lpos, TPos&& tpos, RPos&& rpos)
-    {
-        return concat_inners<Node>(lpos, tpos, rpos);
-    }
-
-    template <typename LPos, typename TPos, typename RPos>
-    static concat_center_pos<Node>
-    visit_leaf(LPos&& lpos, TPos&& tpos, RPos&& rpos)
-    {
-        IMMER_UNREACHABLE;
-    }
-};
-
-template <typename Node>
-struct concat_right_visitor : visitor_base<concat_right_visitor<Node>>
-{
-    using this_t = concat_right_visitor;
-
-    template <typename RPos, typename LPos, typename TPos>
-    static concat_center_pos<Node>
-    visit_inner(RPos&& rpos, LPos&& lpos, TPos&& tpos)
-    {
-        return concat_inners<Node>(lpos, tpos, rpos);
-    }
-
-    template <typename RPos, typename LPos, typename TPos>
-    static concat_center_pos<Node>
-    visit_leaf(RPos&& rpos, LPos&& lpos, TPos&& tpos)
-    {
-        return concat_leafs<Node>(lpos, tpos, rpos);
-    }
-};
-
-template <typename Node>
-struct concat_both_visitor : visitor_base<concat_both_visitor<Node>>
-{
-    using this_t = concat_both_visitor;
-
-    template <typename LPos, typename TPos, typename RPos>
-    static concat_center_pos<Node>
-    visit_inner(LPos&& lpos, TPos&& tpos, RPos&& rpos)
-    {
-        return rpos.first_sub(concat_right_visitor<Node>{}, lpos, tpos);
-    }
-
-    template <typename LPos, typename TPos, typename RPos>
-    static concat_center_pos<Node>
-    visit_leaf(LPos&& lpos, TPos&& tpos, RPos&& rpos)
-    {
-        return rpos.first_sub_leaf(concat_right_visitor<Node>{}, lpos, tpos);
-    }
-};
-
-template <typename Node>
-struct concat_trees_right_visitor
-    : visitor_base<concat_trees_right_visitor<Node>>
-{
-    using this_t = concat_trees_right_visitor;
-
-    template <typename RPos, typename LPos, typename TPos>
-    static concat_center_pos<Node>
-    visit_node(RPos&& rpos, LPos&& lpos, TPos&& tpos)
-    {
-        return concat_inners<Node>(lpos, tpos, rpos);
-    }
-};
-
-template <typename Node>
-struct concat_trees_left_visitor : visitor_base<concat_trees_left_visitor<Node>>
-{
-    using this_t = concat_trees_left_visitor;
-
-    template <typename LPos, typename TPos, typename... Args>
-    static concat_center_pos<Node>
-    visit_node(LPos&& lpos, TPos&& tpos, Args&&... args)
-    {
-        return visit_maybe_relaxed_sub(
-            args..., concat_trees_right_visitor<Node>{}, lpos, tpos);
-    }
-};
-
-template <typename Node>
-relaxed_pos<Node> concat_trees(Node* lroot,
-                               shift_t lshift,
-                               size_t lsize,
-                               Node* ltail,
-                               count_t ltcount,
-                               Node* rroot,
-                               shift_t rshift,
-                               size_t rsize)
-{
-    return visit_maybe_relaxed_sub(lroot,
-                                   lshift,
-                                   lsize,
-                                   concat_trees_left_visitor<Node>{},
-                                   make_leaf_pos(ltail, ltcount),
-                                   rroot,
-                                   rshift,
-                                   rsize)
-        .realize();
-}
-
-template <typename Node>
-relaxed_pos<Node> concat_trees(
-    Node* ltail, count_t ltcount, Node* rroot, shift_t rshift, size_t rsize)
-{
-    return make_singleton_regular_sub_pos(ltail, ltcount)
-        .visit(concat_trees_left_visitor<Node>{},
-               empty_leaf_pos<Node>{},
-               rroot,
-               rshift,
-               rsize)
-        .realize();
-}
-
-template <typename Node>
-using concat_center_mut_pos = concat_center_pos<Node>;
-
-template <typename Node>
-struct concat_merger_mut
-{
-    using node_t = Node;
-    using edit_t = typename Node::edit_t;
-
-    static constexpr auto B  = Node::bits;
-    static constexpr auto BL = Node::bits_leaf;
-
-    using result_t = concat_center_pos<Node>;
-
-    edit_t ec_ = {};
-
-    count_t* curr_;
-    count_t n_;
-    result_t result_;
-    count_t count_      = 0;
-    node_t* candidate_  = nullptr;
-    edit_t candidate_e_ = Node::memory::transience_t::noone;
-
-    concat_merger_mut(edit_t ec,
-                      shift_t shift,
-                      count_t* counts,
-                      count_t n,
-                      edit_t candidate_e,
-                      node_t* candidate)
-        : ec_{ec}
-        , curr_{counts}
-        , n_{n}
-        , result_{shift + B, nullptr, 0}
-    {
-        if (candidate) {
-            candidate->ensure_mutable_relaxed_e(candidate_e, ec);
-            result_.nodes_[0] = candidate;
-        } else {
-            result_.nodes_[0] = node_t::make_inner_r_e(ec);
-        }
-    }
-
-    node_t* to_        = {};
-    count_t to_offset_ = {};
-    size_t to_size_    = {};
-
-    void set_candidate(edit_t candidate_e, node_t* candidate)
-    {
-        candidate_   = candidate;
-        candidate_e_ = candidate_e;
-    }
-
-    void add_child(node_t* p, size_t size)
-    {
-        ++curr_;
-        auto parent  = result_.nodes_[result_.count_ - 1];
-        auto relaxed = parent->relaxed();
-        if (count_ == branches<B>) {
-            parent->relaxed()->d.count = count_;
-            assert(result_.count_ < result_t::max_children);
-            n_ -= branches<B>;
-            if (candidate_) {
-                parent = candidate_;
-                parent->ensure_mutable_relaxed_e(candidate_e_, ec_);
-                candidate_ = nullptr;
-            } else
-                parent = node_t::make_inner_r_e(ec_);
-            count_                         = 0;
-            relaxed                        = parent->relaxed();
-            result_.nodes_[result_.count_] = parent;
-            result_.sizes_[result_.count_] = result_.sizes_[result_.count_ - 1];
-            ++result_.count_;
-        }
-        auto idx = count_++;
-        result_.sizes_[result_.count_ - 1] += size;
-        relaxed->d.sizes[idx] = size + (idx ? relaxed->d.sizes[idx - 1] : 0);
-        parent->inner()[idx]  = p;
-    };
-
-    template <typename Pos>
-    void merge_leaf(Pos&& p, edit_t e)
-    {
-        auto from       = p.node();
-        auto from_size  = p.size();
-        auto from_count = p.count();
-        assert(from_size);
-        if (!to_ && *curr_ == from_count) {
-            add_child(from, from_size);
-        } else {
-            auto from_offset = count_t{};
-            auto from_data   = from->leaf();
-            auto from_mutate = from->can_mutate(e);
-            do {
-                if (!to_) {
-                    if (from_mutate) {
-                        node_t::ownee(from) = ec_;
-                        to_                 = from->inc();
-                        assert(from_count);
-                    } else {
-                        to_ = node_t::make_leaf_e(ec_);
-                    }
-                    to_offset_ = 0;
-                }
-                auto data = to_->leaf();
-                auto to_copy =
-                    std::min(from_count - from_offset, *curr_ - to_offset_);
-                if (from == to_) {
-                    if (from_offset != to_offset_)
-                        std::move(from_data + from_offset,
-                                  from_data + from_offset + to_copy,
-                                  data + to_offset_);
-                } else {
-                    if (!from_mutate)
-                        std::uninitialized_copy(from_data + from_offset,
-                                                from_data + from_offset +
-                                                    to_copy,
-                                                data + to_offset_);
-                    else
-                        detail::uninitialized_move(from_data + from_offset,
-                                                   from_data + from_offset +
-                                                       to_copy,
-                                                   data + to_offset_);
-                }
-                to_offset_ += to_copy;
-                from_offset += to_copy;
-                if (*curr_ == to_offset_) {
-                    add_child(to_, to_offset_);
-                    to_ = nullptr;
-                }
-            } while (from_offset != from_count);
-        }
-    }
-
-    template <typename Pos>
-    void merge_inner(Pos&& p, edit_t e)
-    {
-        auto from       = p.node();
-        auto from_size  = p.size();
-        auto from_count = p.count();
-        assert(from_size);
-        if (!to_ && *curr_ == from_count) {
-            add_child(from, from_size);
-        } else {
-            auto from_offset = count_t{};
-            auto from_data   = from->inner();
-            auto from_mutate = from->can_relax() && from->can_mutate(e);
-            do {
-                if (!to_) {
-                    if (from_mutate) {
-                        node_t::ownee(from) = ec_;
-                        from->ensure_mutable_relaxed_e(e, ec_);
-                        to_ = from;
-                    } else {
-                        to_ = node_t::make_inner_r_e(ec_);
-                    }
-                    to_offset_ = 0;
-                    to_size_   = 0;
-                }
-                auto data = to_->inner();
-                auto to_copy =
-                    std::min(from_count - from_offset, *curr_ - to_offset_);
-                auto sizes = to_->relaxed()->d.sizes;
-                if (from != to_ || from_offset != to_offset_) {
-                    std::copy(from_data + from_offset,
-                              from_data + from_offset + to_copy,
-                              data + to_offset_);
-                    p.copy_sizes(
-                        from_offset, to_copy, to_size_, sizes + to_offset_);
-                }
-                to_offset_ += to_copy;
-                from_offset += to_copy;
-                to_size_ = sizes[to_offset_ - 1];
-                if (*curr_ == to_offset_) {
-                    to_->relaxed()->d.count = to_offset_;
-                    add_child(to_, to_size_);
-                    to_ = nullptr;
-                }
-            } while (from_offset != from_count);
-        }
-    }
-
-    concat_center_pos<Node> finish() const
-    {
-        assert(!to_);
-        result_.nodes_[result_.count_ - 1]->relaxed()->d.count = count_;
-        return result_;
-    }
-
-    void abort()
-    {
-        // We may have mutated stuff the tree in place, leaving
-        // everything in a corrupted state...  It should be possible
-        // to define cleanup properly, but that is a task for some
-        // other day... ;)
-        std::terminate();
-    }
-};
-
-struct concat_merger_mut_visitor : visitor_base<concat_merger_mut_visitor>
-{
-    using this_t = concat_merger_mut_visitor;
-
-    template <typename Pos, typename Merger>
-    static void visit_inner(Pos&& p, Merger& merger, edit_type<Pos> e)
-    {
-        merger.merge_inner(p, e);
-    }
-
-    template <typename Pos, typename Merger>
-    static void visit_leaf(Pos&& p, Merger& merger, edit_type<Pos> e)
-    {
-        merger.merge_leaf(p, e);
-    }
-};
-
-template <bits_t B, bits_t BL>
-struct concat_rebalance_plan_mut : concat_rebalance_plan<B, BL>
-{
-    using this_t = concat_rebalance_plan_mut;
-
-    template <typename LPos, typename CPos, typename RPos>
-    concat_center_mut_pos<node_type<CPos>> merge(edit_type<CPos> ec,
-                                                 edit_type<CPos> el,
-                                                 LPos&& lpos,
-                                                 CPos&& cpos,
-                                                 edit_type<CPos> er,
-                                                 RPos&& rpos)
-    {
-        using node_t    = node_type<CPos>;
-        using merger_t  = concat_merger_mut<node_t>;
-        using visitor_t = concat_merger_mut_visitor;
-        auto lnode      = ((node_t*) lpos.node());
-        auto rnode      = ((node_t*) rpos.node());
-        auto lmut2      = lnode && lnode->can_relax() && lnode->can_mutate(el);
-        auto rmut2      = rnode && rnode->can_relax() && rnode->can_mutate(er);
-        auto merger     = merger_t{ec,
-                               cpos.shift(),
-                               this->counts,
-                               this->n,
-                               el,
-                               lmut2 ? lnode : nullptr};
-        try {
-            lpos.each_left_sub(visitor_t{}, merger, el);
-            cpos.each_sub(visitor_t{}, merger, ec);
-            if (rmut2)
-                merger.set_candidate(er, rnode);
-            rpos.each_right_sub(visitor_t{}, merger, er);
-            return merger.finish();
-        } catch (...) {
-            merger.abort();
-            throw;
-        }
-    }
-};
-
-template <typename Node, typename LPos, typename CPos, typename RPos>
-concat_center_pos<Node> concat_rebalance_mut(edit_type<Node> ec,
-                                             edit_type<Node> el,
-                                             LPos&& lpos,
-                                             CPos&& cpos,
-                                             edit_type<Node> er,
-                                             RPos&& rpos)
-{
-    auto plan = concat_rebalance_plan_mut<Node::bits, Node::bits_leaf>{};
-    plan.fill(lpos, cpos, rpos);
-    plan.shuffle(cpos.shift());
-    return plan.merge(ec, el, lpos, cpos, er, rpos);
-}
-
-template <typename Node, typename LPos, typename TPos, typename RPos>
-concat_center_mut_pos<Node> concat_leafs_mut(edit_type<Node> ec,
-                                             edit_type<Node> el,
-                                             LPos&& lpos,
-                                             TPos&& tpos,
-                                             edit_type<Node> er,
-                                             RPos&& rpos)
-{
-    static_assert(Node::bits >= 2, "");
-    assert(lpos.shift() == tpos.shift());
-    assert(lpos.shift() == rpos.shift());
-    assert(lpos.shift() == 0);
-    if (tpos.count() > 0)
-        return {
-            Node::bits_leaf,
-            lpos.node(),
-            lpos.count(),
-            tpos.node(),
-            tpos.count(),
-            rpos.node(),
-            rpos.count(),
-        };
-    else
-        return {
-            Node::bits_leaf,
-            lpos.node(),
-            lpos.count(),
-            rpos.node(),
-            rpos.count(),
-        };
-}
-
-template <typename Node>
-struct concat_left_mut_visitor;
-template <typename Node>
-struct concat_right_mut_visitor;
-template <typename Node>
-struct concat_both_mut_visitor;
-
-template <typename Node, typename LPos, typename TPos, typename RPos>
-concat_center_mut_pos<Node> concat_inners_mut(edit_type<Node> ec,
-                                              edit_type<Node> el,
-                                              LPos&& lpos,
-                                              TPos&& tpos,
-                                              edit_type<Node> er,
-                                              RPos&& rpos)
-{
-    auto lshift = lpos.shift();
-    auto rshift = rpos.shift();
-    // lpos.node() can be null it is a singleton_regular_sub_pos<...>,
-    // this is, when the tree is just a tail...
-    if (lshift > rshift) {
-        auto cpos = lpos.last_sub(
-            concat_left_mut_visitor<Node>{}, ec, el, tpos, er, rpos);
-        return concat_rebalance_mut<Node>(
-            ec, el, lpos, cpos, er, null_sub_pos{});
-    } else if (lshift < rshift) {
-        auto cpos = rpos.first_sub(
-            concat_right_mut_visitor<Node>{}, ec, el, lpos, tpos, er);
-        return concat_rebalance_mut<Node>(
-            ec, el, null_sub_pos{}, cpos, er, rpos);
-    } else {
-        assert(lshift == rshift);
-        assert(Node::bits_leaf == 0u || lshift > 0);
-        auto cpos = lpos.last_sub(
-            concat_both_mut_visitor<Node>{}, ec, el, tpos, er, rpos);
-        return concat_rebalance_mut<Node>(ec, el, lpos, cpos, er, rpos);
-    }
-}
-
-template <typename Node>
-struct concat_left_mut_visitor : visitor_base<concat_left_mut_visitor<Node>>
-{
-    using this_t = concat_left_mut_visitor;
-    using edit_t = typename Node::edit_t;
-
-    template <typename LPos, typename TPos, typename RPos>
-    static concat_center_mut_pos<Node> visit_inner(
-        LPos&& lpos, edit_t ec, edit_t el, TPos&& tpos, edit_t er, RPos&& rpos)
-    {
-        return concat_inners_mut<Node>(ec, el, lpos, tpos, er, rpos);
-    }
-
-    template <typename LPos, typename TPos, typename RPos>
-    static concat_center_mut_pos<Node> visit_leaf(
-        LPos&& lpos, edit_t ec, edit_t el, TPos&& tpos, edit_t er, RPos&& rpos)
-    {
-        IMMER_UNREACHABLE;
-    }
-};
-
-template <typename Node>
-struct concat_right_mut_visitor : visitor_base<concat_right_mut_visitor<Node>>
-{
-    using this_t = concat_right_mut_visitor;
-    using edit_t = typename Node::edit_t;
-
-    template <typename RPos, typename LPos, typename TPos>
-    static concat_center_mut_pos<Node> visit_inner(
-        RPos&& rpos, edit_t ec, edit_t el, LPos&& lpos, TPos&& tpos, edit_t er)
-    {
-        return concat_inners_mut<Node>(ec, el, lpos, tpos, er, rpos);
-    }
-
-    template <typename RPos, typename LPos, typename TPos>
-    static concat_center_mut_pos<Node> visit_leaf(
-        RPos&& rpos, edit_t ec, edit_t el, LPos&& lpos, TPos&& tpos, edit_t er)
-    {
-        return concat_leafs_mut<Node>(ec, el, lpos, tpos, er, rpos);
-    }
-};
-
-template <typename Node>
-struct concat_both_mut_visitor : visitor_base<concat_both_mut_visitor<Node>>
-{
-    using this_t = concat_both_mut_visitor;
-    using edit_t = typename Node::edit_t;
-
-    template <typename LPos, typename TPos, typename RPos>
-    static concat_center_mut_pos<Node> visit_inner(
-        LPos&& lpos, edit_t ec, edit_t el, TPos&& tpos, edit_t er, RPos&& rpos)
-    {
-        return rpos.first_sub(
-            concat_right_mut_visitor<Node>{}, ec, el, lpos, tpos, er);
-    }
-
-    template <typename LPos, typename TPos, typename RPos>
-    static concat_center_mut_pos<Node> visit_leaf(
-        LPos&& lpos, edit_t ec, edit_t el, TPos&& tpos, edit_t er, RPos&& rpos)
-    {
-        return rpos.first_sub_leaf(
-            concat_right_mut_visitor<Node>{}, ec, el, lpos, tpos, er);
-    }
-};
-
-template <typename Node>
-struct concat_trees_right_mut_visitor
-    : visitor_base<concat_trees_right_mut_visitor<Node>>
-{
-    using this_t = concat_trees_right_mut_visitor;
-    using edit_t = typename Node::edit_t;
-
-    template <typename RPos, typename LPos, typename TPos>
-    static concat_center_mut_pos<Node> visit_node(
-        RPos&& rpos, edit_t ec, edit_t el, LPos&& lpos, TPos&& tpos, edit_t er)
-    {
-        return concat_inners_mut<Node>(ec, el, lpos, tpos, er, rpos);
-    }
-};
-
-template <typename Node>
-struct concat_trees_left_mut_visitor
-    : visitor_base<concat_trees_left_mut_visitor<Node>>
-{
-    using this_t = concat_trees_left_mut_visitor;
-    using edit_t = typename Node::edit_t;
-
-    template <typename LPos, typename TPos, typename... Args>
-    static concat_center_mut_pos<Node> visit_node(LPos&& lpos,
-                                                  edit_t ec,
-                                                  edit_t el,
-                                                  TPos&& tpos,
-                                                  edit_t er,
-                                                  Args&&... args)
-    {
-        return visit_maybe_relaxed_sub(args...,
-                                       concat_trees_right_mut_visitor<Node>{},
-                                       ec,
-                                       el,
-                                       lpos,
-                                       tpos,
-                                       er);
-    }
-};
-
-template <typename Node>
-relaxed_pos<Node> concat_trees_mut(edit_type<Node> ec,
-                                   edit_type<Node> el,
-                                   Node* lroot,
-                                   shift_t lshift,
-                                   size_t lsize,
-                                   Node* ltail,
-                                   count_t ltcount,
-                                   edit_type<Node> er,
-                                   Node* rroot,
-                                   shift_t rshift,
-                                   size_t rsize)
-{
-    return visit_maybe_relaxed_sub(lroot,
-                                   lshift,
-                                   lsize,
-                                   concat_trees_left_mut_visitor<Node>{},
-                                   ec,
-                                   el,
-                                   make_leaf_pos(ltail, ltcount),
-                                   er,
-                                   rroot,
-                                   rshift,
-                                   rsize)
-        .realize_e(ec);
-}
-
-template <typename Node>
-relaxed_pos<Node> concat_trees_mut(edit_type<Node> ec,
-                                   edit_type<Node> el,
-                                   Node* ltail,
-                                   count_t ltcount,
-                                   edit_type<Node> er,
-                                   Node* rroot,
-                                   shift_t rshift,
-                                   size_t rsize)
-{
-    return make_singleton_regular_sub_pos(ltail, ltcount)
-        .visit(concat_trees_left_mut_visitor<Node>{},
-               ec,
-               el,
-               empty_leaf_pos<Node>{},
-               er,
-               rroot,
-               rshift,
-               rsize)
-        .realize_e(ec);
-}
-
-} // namespace rbts
-} // namespace detail
-} // namespace immer