From cbebb3d66f41ac46d8b50137babc4c6d8754e0ab Mon Sep 17 00:00:00 2001
From: kynex7510 <nikkitten3@gmail.com>
Date: Wed, 20 Mar 2024 16:52:48 +0100
Subject: [PATCH] MSVC UMap, USet

---
 loader/include/Geode/c++stl/gdstdlib.hpp      |    1 -
 .../include/Geode/c++stl/msvc/allocator.hpp   |   34 +
 loader/include/Geode/c++stl/msvc/umap.hpp     |  562 ++++++
 loader/include/Geode/c++stl/msvc/uset.hpp     |  417 ++++
 loader/include/Geode/c++stl/msvc/xhash.hpp    | 1793 +++++++++++++++++
 loader/include/Geode/c++stl/msvcstl.hpp       |   10 +-
 loader/src/platform/windows/gdstdlib.cpp      |   22 +
 7 files changed, 2834 insertions(+), 5 deletions(-)
 create mode 100644 loader/include/Geode/c++stl/msvc/allocator.hpp
 create mode 100644 loader/include/Geode/c++stl/msvc/umap.hpp
 create mode 100644 loader/include/Geode/c++stl/msvc/uset.hpp
 create mode 100644 loader/include/Geode/c++stl/msvc/xhash.hpp

diff --git a/loader/include/Geode/c++stl/gdstdlib.hpp b/loader/include/Geode/c++stl/gdstdlib.hpp
index e76dadf3..4f80cc90 100644
--- a/loader/include/Geode/c++stl/gdstdlib.hpp
+++ b/loader/include/Geode/c++stl/gdstdlib.hpp
@@ -7,6 +7,5 @@
 #if defined(GEODE_IS_ANDROID)
 #include "gnustl.hpp"
 #else
-// this is quite funny but msvcstl is just all aliases
 #include "msvcstl.hpp"
 #endif
diff --git a/loader/include/Geode/c++stl/msvc/allocator.hpp b/loader/include/Geode/c++stl/msvc/allocator.hpp
new file mode 100644
index 00000000..19d066fc
--- /dev/null
+++ b/loader/include/Geode/c++stl/msvc/allocator.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <cstddef>
+#include <type_traits>
+
+namespace geode::stl {
+
+    GEODE_DLL void* operatorNew(std::size_t size);
+    GEODE_DLL void operatorDelete(void* ptr);
+
+    template <class T>
+    struct allocator {
+        using value_type = T;
+        using size_type	= std::size_t;
+        using difference_type = std::ptrdiff_t;
+        using propagate_on_container_move_assignment = std::true_type;
+
+        constexpr allocator() noexcept {}
+        constexpr allocator(const allocator& other) noexcept {}
+
+        template<class U>
+        constexpr allocator(const allocator<U>& other) noexcept {}
+
+        constexpr ~allocator() {}
+
+        [[nodiscard]] T* allocate(std::size_t n) {
+            return reinterpret_cast<T*>(operatorNew(n * sizeof(T)));
+        }
+
+        void deallocate(T* p, std::size_t n) {
+            operatorDelete(reinterpret_cast<void*>(p));
+        }
+    };
+}
\ No newline at end of file
diff --git a/loader/include/Geode/c++stl/msvc/umap.hpp b/loader/include/Geode/c++stl/msvc/umap.hpp
new file mode 100644
index 00000000..9836b0b9
--- /dev/null
+++ b/loader/include/Geode/c++stl/msvc/umap.hpp
@@ -0,0 +1,562 @@
+// unordered_map standard header
+
+// Copyright (c) Microsoft Corporation.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// Per Apache License, Version 2.0, Section 4, Point b: I (kynex7510) changed this file.
+
+#ifndef _GEODE_UNORDERED_MAP_
+#define _GEODE_UNORDERED_MAP_
+#include <yvals_core.h>
+#if _STL_COMPILER_PREPROCESSOR
+#include "xhash.hpp"
+
+#if _HAS_CXX17
+#include <xpolymorphic_allocator.h>
+#endif // _HAS_CXX17
+
+#pragma pack(push, _CRT_PACKING)
+#pragma warning(push, _STL_WARNING_LEVEL)
+#pragma warning(disable : _STL_DISABLED_WARNINGS)
+_STL_DISABLE_CLANG_WARNINGS
+#pragma push_macro("new")
+#undef new
+
+namespace geode::stl {
+
+template <class _Kty, // key type
+    class _Ty, // mapped type
+    class _Tr, // comparator predicate type
+    class _Alloc, // actual _STD allocator type (should be value _STD allocator)
+    bool _Mfl> // true if multiple equivalent keys are permitted
+class _Umap_traits : public _Tr { // traits required to make _Hash behave like a map
+public:
+    using key_type            = _Kty;
+    using value_type          = _STD pair<const _Kty, _Ty>;
+    using _Mutable_value_type = _STD pair<_Kty, _Ty>;
+    using key_compare         = _Tr;
+    using allocator_type      = _Alloc;
+#if _HAS_CXX17
+    using node_type = _STD _Node_handle<_STD _List_node<value_type, typename _STD allocator_traits<_Alloc>::void_pointer>, _Alloc,
+        _STD _Node_handle_map_base, _Kty, _Ty>;
+#endif // _HAS_CXX17
+
+    static constexpr bool _Multi    = _Mfl;
+    static constexpr bool _Standard = true;
+
+    template <class... _Args>
+    using _In_place_key_extractor = _STD _In_place_key_extract_map<_Kty, _Args...>;
+
+    _Umap_traits() = default;
+
+    explicit _Umap_traits(const _Tr& _Traits) noexcept(_STD is_nothrow_copy_constructible_v<_Tr>) : _Tr(_Traits) {}
+
+    using value_compare = void; // TRANSITION, remove when _Standard becomes unconditionally true
+
+    template <class _Ty1, class _Ty2>
+    static const _Kty& _Kfn(const _STD pair<_Ty1, _Ty2>& _Val) noexcept { // extract key from element value
+        return _Val.first;
+    }
+
+    template <class _Ty1, class _Ty2>
+    static const _Ty2& _Nonkfn(const _STD pair<_Ty1, _Ty2>& _Val) noexcept { // extract non-key from element value
+        return _Val.second;
+    }
+};
+
+/*_EXPORT_STD*/ template <class _Kty, class _Ty, class _Hasher = _STD hash<_Kty>, class _Keyeq = _STD equal_to<_Kty>,
+    class _Alloc = _STD allocator<_STD pair<const _Kty, _Ty>>>
+class unordered_map : public _Hash<_Umap_traits<_Kty, _Ty, _STD _Uhash_compare<_Kty, _Hasher, _Keyeq>, _Alloc, false>> {
+    // hash table of {key, mapped} values, unique keys
+public:
+    static_assert(!_ENFORCE_MATCHING_ALLOCATORS || _STD is_same_v<_STD pair<const _Kty, _Ty>, typename _Alloc::value_type>,
+        _MISMATCHED_ALLOCATOR_MESSAGE("unordered_map<Key, Value, Hasher, Eq, Allocator>", "_STD pair<const Key, Value>"));
+    static_assert(_STD is_object_v<_Kty>, "The C++ Standard forbids containers of non-object types "
+                                     "because of [container.requirements].");
+
+private:
+    using _Mytraits      = _STD _Uhash_compare<_Kty, _Hasher, _Keyeq>;
+    using _Mybase        = _Hash<_Umap_traits<_Kty, _Ty, _Mytraits, _Alloc, false>>;
+    using _Alnode        = typename _Mybase::_Alnode;
+    using _Alnode_traits = typename _Mybase::_Alnode_traits;
+    using _Nodeptr       = typename _Mybase::_Nodeptr;
+    using _Key_compare   = typename _Mybase::_Key_compare;
+
+public:
+    using hasher      = _Hasher;
+    using key_type    = _Kty;
+    using mapped_type = _Ty;
+    using key_equal   = _Keyeq;
+
+    using value_type      = _STD pair<const _Kty, _Ty>;
+    using allocator_type  = typename _Mybase::allocator_type;
+    using size_type       = typename _Mybase::size_type;
+    using difference_type = typename _Mybase::difference_type;
+    using pointer         = typename _Mybase::pointer;
+    using const_pointer   = typename _Mybase::const_pointer;
+    using reference       = value_type&;
+    using const_reference = const value_type&;
+    using iterator        = typename _Mybase::iterator;
+    using const_iterator  = typename _Mybase::const_iterator;
+
+    using local_iterator       = typename _Mybase::iterator;
+    using const_local_iterator = typename _Mybase::const_iterator;
+
+#if _HAS_CXX17
+    using insert_return_type = _STD _Insert_return_type<iterator, typename _Mybase::node_type>;
+#endif // _HAS_CXX17
+
+    unordered_map() : _Mybase(_Key_compare(), allocator_type()) {}
+
+    explicit unordered_map(const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {}
+
+    unordered_map(const unordered_map& _Right)
+        : _Mybase(_Right, _Alnode_traits::select_on_container_copy_construction(_Right._Getal())) {}
+
+    unordered_map(const unordered_map& _Right, const allocator_type& _Al) : _Mybase(_Right, _Al) {}
+
+    explicit unordered_map(size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+    }
+
+    unordered_map(size_type _Buckets, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
+        _Mybase::rehash(_Buckets);
+    }
+
+    unordered_map(size_type _Buckets, const hasher& _Hasharg) : _Mybase(_Key_compare(_Hasharg), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+    }
+
+    unordered_map(size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg), _Al) {
+        _Mybase::rehash(_Buckets);
+    }
+
+    unordered_map(size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+    }
+
+    unordered_map(size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg, const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
+        _Mybase::rehash(_Buckets);
+    }
+
+    template <class _Iter>
+    unordered_map(_Iter _First, _Iter _Last) : _Mybase(_Key_compare(), allocator_type()) {
+        insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_map(_Iter _First, _Iter _Last, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
+        insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_map(_Iter _First, _Iter _Last, size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+        insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_map(_Iter _First, _Iter _Last, size_type _Buckets, const allocator_type& _Al)
+        : _Mybase(_Key_compare(), _Al) {
+        _Mybase::rehash(_Buckets);
+        insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_map(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg)
+        : _Mybase(_Key_compare(_Hasharg), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+        insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_map(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg), _Al) {
+        _Mybase::rehash(_Buckets);
+        insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_map(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+        insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_map(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg,
+        const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
+        _Mybase::rehash(_Buckets);
+        insert(_First, _Last);
+    }
+
+#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_map(from_range_t, _Rng&& _Range) : _Mybase(_Key_compare(), allocator_type()) {
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_map(from_range_t, _Rng&& _Range, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_map(from_range_t, _Rng&& _Range, size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_map(from_range_t, _Rng&& _Range, size_type _Buckets, const allocator_type& _Al)
+        : _Mybase(_Key_compare(), _Al) {
+        _Mybase::rehash(_Buckets);
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_map(from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg)
+        : _Mybase(_Key_compare(_Hasharg), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_map(from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg), _Al) {
+        _Mybase::rehash(_Buckets);
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_map(from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_map(from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg,
+        const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
+        _Mybase::rehash(_Buckets);
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)
+
+    unordered_map& operator=(const unordered_map& _Right) {
+        _Mybase::operator=(_Right);
+        return *this;
+    }
+
+    unordered_map(unordered_map&& _Right) : _Mybase(_STD move(_Right)) {}
+
+    unordered_map(unordered_map&& _Right, const allocator_type& _Al) : _Mybase(_STD move(_Right), _Al) {}
+
+    unordered_map& operator=(unordered_map&& _Right) noexcept(_Alnode_traits::is_always_equal::value&&
+            _STD is_nothrow_move_assignable_v<_Hasher>&& _STD is_nothrow_move_assignable_v<_Keyeq>) {
+        _Mybase::operator=(_STD move(_Right));
+        return *this;
+    }
+
+    mapped_type& operator[](key_type&& _Keyval) {
+        return this->_Try_emplace(_STD move(_Keyval)).first->_Myval.second;
+    }
+
+    void swap(unordered_map& _Right) noexcept(noexcept(_Mybase::swap(_Right))) {
+        _Mybase::swap(_Right);
+    }
+
+    using _Mybase::insert;
+
+    template <class _Valty, _STD enable_if_t<_STD is_constructible_v<value_type, _Valty>, int> = 0>
+    _STD pair<iterator, bool> insert(_Valty&& _Val) {
+        return this->emplace(_STD forward<_Valty>(_Val));
+    }
+
+    template <class _Valty, _STD enable_if_t<_STD is_constructible_v<value_type, _Valty>, int> = 0>
+    iterator insert(const_iterator _Where, _Valty&& _Val) {
+        return this->emplace_hint(_Where, _STD forward<_Valty>(_Val));
+    }
+
+    template <class... _Mappedty>
+    _STD pair<iterator, bool> try_emplace(const key_type& _Keyval, _Mappedty&&... _Mapval) {
+        const auto _Result = this->_Try_emplace(_Keyval, _STD forward<_Mappedty>(_Mapval)...);
+        return {this->_List._Make_iter(_Result.first), _Result.second};
+    }
+
+    template <class... _Mappedty>
+    _STD pair<iterator, bool> try_emplace(key_type&& _Keyval, _Mappedty&&... _Mapval) {
+        const auto _Result = this->_Try_emplace(_STD move(_Keyval), _STD forward<_Mappedty>(_Mapval)...);
+        return {this->_List._Make_iter(_Result.first), _Result.second};
+    }
+
+    template <class... _Mappedty>
+    iterator try_emplace(const const_iterator _Hint, const key_type& _Keyval, _Mappedty&&... _Mapval) {
+        return this->_List._Make_iter(
+            this->_Try_emplace_hint(_Hint._Ptr, _Keyval, _STD forward<_Mappedty>(_Mapval)...));
+    }
+
+    template <class... _Mappedty>
+    iterator try_emplace(const const_iterator _Hint, key_type&& _Keyval, _Mappedty&&... _Mapval) {
+        return this->_List._Make_iter(
+            this->_Try_emplace_hint(_Hint._Ptr, _STD move(_Keyval), _STD forward<_Mappedty>(_Mapval)...));
+    }
+
+private:
+    template <class _Keyty, class _Mappedty>
+    _STD pair<iterator, bool> _Insert_or_assign(_Keyty&& _Keyval_arg, _Mappedty&& _Mapval) {
+        const auto& _Keyval   = _Keyval_arg;
+        const size_t _Hashval = this->_Traitsobj(_Keyval);
+        auto _Target          = this->_Find_last(_Keyval, _Hashval);
+        if (_Target._Duplicate) {
+            _Target._Duplicate->_Myval.second = _STD forward<_Mappedty>(_Mapval);
+            return {this->_List._Make_iter(_Target._Duplicate), false};
+        }
+
+        this->_Check_max_size();
+        // invalidates _Keyval:
+        _STD _List_node_emplace_op2<_Alnode> _Newnode(
+            this->_Getal(), _STD forward<_Keyty>(_Keyval_arg), _STD forward<_Mappedty>(_Mapval));
+        if (this->_Check_rehash_required_1()) {
+            this->_Rehash_for_1();
+            _Target = this->_Find_last(_Newnode._Ptr->_Myval.first, _Hashval);
+        }
+
+        return {this->_List._Make_iter(
+                    this->_Insert_new_node_before(_Hashval, _Target._Insert_before, _Newnode._Release())),
+            true};
+    }
+
+    template <class _Keyty, class _Mappedty>
+    iterator _Insert_or_assign(const _Nodeptr _Hint, _Keyty&& _Keyval_arg, _Mappedty&& _Mapval) {
+        const auto& _Keyval   = _Keyval_arg;
+        const size_t _Hashval = this->_Traitsobj(_Keyval);
+        auto _Target          = this->_Find_hint(_Hint, _Keyval, _Hashval);
+        if (_Target._Duplicate) {
+            _Target._Duplicate->_Myval.second = _STD forward<_Mappedty>(_Mapval);
+            return this->_List._Make_iter(_Target._Duplicate);
+        }
+
+        this->_Check_max_size();
+        // invalidates _Keyval:
+        _STD _List_node_emplace_op2<_Alnode> _Newnode(
+            this->_Getal(), _STD forward<_Keyty>(_Keyval_arg), _STD forward<_Mappedty>(_Mapval));
+        if (this->_Check_rehash_required_1()) {
+            this->_Rehash_for_1();
+            _Target = this->_Find_hint(_Hint, _Newnode._Ptr->_Myval.first, _Hashval);
+        }
+
+        return this->_List._Make_iter(
+            this->_Insert_new_node_before(_Hashval, _Target._Insert_before, _Newnode._Release()));
+    }
+
+public:
+    template <class _Mappedty>
+    _STD pair<iterator, bool> insert_or_assign(const key_type& _Keyval, _Mappedty&& _Mapval) {
+        return _Insert_or_assign(_Keyval, _STD forward<_Mappedty>(_Mapval));
+    }
+
+    template <class _Mappedty>
+    _STD pair<iterator, bool> insert_or_assign(key_type&& _Keyval, _Mappedty&& _Mapval) {
+        return _Insert_or_assign(_STD move(_Keyval), _STD forward<_Mappedty>(_Mapval));
+    }
+
+    template <class _Mappedty>
+    iterator insert_or_assign(const_iterator _Hint, const key_type& _Keyval, _Mappedty&& _Mapval) {
+        return _Insert_or_assign(_Hint._Ptr, _Keyval, _STD forward<_Mappedty>(_Mapval));
+    }
+
+    template <class _Mappedty>
+    iterator insert_or_assign(const_iterator _Hint, key_type&& _Keyval, _Mappedty&& _Mapval) {
+        return _Insert_or_assign(_Hint._Ptr, _STD move(_Keyval), _STD forward<_Mappedty>(_Mapval));
+    }
+
+    unordered_map(_STD initializer_list<value_type> _Ilist) : _Mybase(_Key_compare(), allocator_type()) {
+        insert(_Ilist);
+    }
+
+    unordered_map(_STD initializer_list<value_type> _Ilist, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
+        insert(_Ilist);
+    }
+
+    unordered_map(_STD initializer_list<value_type> _Ilist, size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+        insert(_Ilist);
+    }
+
+    unordered_map(_STD initializer_list<value_type> _Ilist, size_type _Buckets, const allocator_type& _Al)
+        : _Mybase(_Key_compare(), _Al) {
+        _Mybase::rehash(_Buckets);
+        insert(_Ilist);
+    }
+
+    unordered_map(_STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg)
+        : _Mybase(_Key_compare(_Hasharg), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+        insert(_Ilist);
+    }
+
+    unordered_map(
+        _STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg), _Al) {
+        _Mybase::rehash(_Buckets);
+        insert(_Ilist);
+    }
+
+    unordered_map(
+        _STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+        insert(_Ilist);
+    }
+
+    unordered_map(_STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg,
+        const _Keyeq& _Keyeqarg, const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
+        _Mybase::rehash(_Buckets);
+        insert(_Ilist);
+    }
+
+    unordered_map& operator=(_STD initializer_list<value_type> _Ilist) {
+        _Mybase::clear();
+        insert(_Ilist);
+        return *this;
+    }
+
+    _NODISCARD hasher hash_function() const {
+        return _Mybase::_Traitsobj._Mypair._Get_first();
+    }
+
+    _NODISCARD key_equal key_eq() const {
+        return _Mybase::_Traitsobj._Mypair._Myval2._Get_first();
+    }
+
+    mapped_type& operator[](const key_type& _Keyval) {
+        return this->_Try_emplace(_Keyval).first->_Myval.second;
+    }
+
+    _NODISCARD mapped_type& at(const key_type& _Keyval) {
+        const auto _Target = this->_Find_last(_Keyval, this->_Traitsobj(_Keyval));
+        if (_Target._Duplicate) {
+            return _Target._Duplicate->_Myval.second;
+        }
+
+        _STD _Xout_of_range("invalid unordered_map<K, T> key");
+    }
+
+    _NODISCARD const mapped_type& at(const key_type& _Keyval) const {
+        const auto _Target = this->_Find_last(_Keyval, this->_Traitsobj(_Keyval));
+        if (_Target._Duplicate) {
+            return _Target._Duplicate->_Myval.second;
+        }
+
+        _STD _Xout_of_range("invalid unordered_map<K, T> key");
+    }
+
+    using _Mybase::_Unchecked_begin;
+    using _Mybase::_Unchecked_end;
+};
+
+#if _HAS_CXX17
+template <class _Iter, class _Hasher = _STD hash<_STD _Guide_key_t<_Iter>>, class _Keyeq = _STD equal_to<_STD _Guide_key_t<_Iter>>,
+    class _Alloc = _STD allocator<_STD _Guide_pair_t<_Iter>>,
+    _STD enable_if_t<
+        _STD conjunction_v<_STD _Is_iterator<_Iter>, _Is_hasher<_Hasher>, _STD negation<_STD _Is_allocator<_Keyeq>>, _STD _Is_allocator<_Alloc>>,
+        int> = 0>
+unordered_map(_Iter, _Iter, _STD _Guide_size_type_t<_Alloc> = 0, _Hasher = _Hasher(), _Keyeq = _Keyeq(), _Alloc = _Alloc())
+    -> unordered_map<_STD _Guide_key_t<_Iter>, _STD _Guide_val_t<_Iter>, _Hasher, _Keyeq, _Alloc>;
+
+template <class _Kty, class _Ty, class _Hasher = _STD hash<_Kty>, class _Keyeq = _STD equal_to<_Kty>,
+    class _Alloc = _STD allocator<_STD pair<const _Kty, _Ty>>,
+    _STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD negation<_STD _Is_allocator<_Keyeq>>, _STD _Is_allocator<_Alloc>>, int> = 0>
+unordered_map(_STD initializer_list<_STD pair<_Kty, _Ty>>, _STD _Guide_size_type_t<_Alloc> = 0, _Hasher = _Hasher(), _Keyeq = _Keyeq(),
+    _Alloc = _Alloc()) -> unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>;
+
+template <class _Iter, class _Alloc, _STD enable_if_t<_STD conjunction_v<_STD _Is_iterator<_Iter>, _STD _Is_allocator<_Alloc>>, int> = 0>
+unordered_map(_Iter, _Iter, _Alloc) -> unordered_map<_STD _Guide_key_t<_Iter>, _STD _Guide_val_t<_Iter>,
+    _STD hash<_STD _Guide_key_t<_Iter>>, _STD equal_to<_STD _Guide_key_t<_Iter>>, _Alloc>;
+
+template <class _Iter, class _Alloc, _STD enable_if_t<_STD conjunction_v<_STD _Is_iterator<_Iter>, _STD _Is_allocator<_Alloc>>, int> = 0>
+unordered_map(_Iter, _Iter, _STD _Guide_size_type_t<_Alloc>, _Alloc) -> unordered_map<_STD _Guide_key_t<_Iter>,
+    _STD _Guide_val_t<_Iter>, _STD hash<_STD _Guide_key_t<_Iter>>, _STD equal_to<_STD _Guide_key_t<_Iter>>, _Alloc>;
+
+template <class _Iter, class _Hasher, class _Alloc,
+    _STD enable_if_t<_STD conjunction_v<_STD _Is_iterator<_Iter>, _Is_hasher<_Hasher>, _STD _Is_allocator<_Alloc>>, int> = 0>
+unordered_map(_Iter, _Iter, _STD _Guide_size_type_t<_Alloc>, _Hasher, _Alloc)
+    -> unordered_map<_STD _Guide_key_t<_Iter>, _STD _Guide_val_t<_Iter>, _Hasher, _STD equal_to<_STD _Guide_key_t<_Iter>>, _Alloc>;
+
+template <class _Kty, class _Ty, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
+unordered_map(_STD initializer_list<_STD pair<_Kty, _Ty>>, _Alloc)
+    -> unordered_map<_Kty, _Ty, _STD hash<_Kty>, _STD equal_to<_Kty>, _Alloc>;
+
+template <class _Kty, class _Ty, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
+unordered_map(_STD initializer_list<_STD pair<_Kty, _Ty>>, _STD _Guide_size_type_t<_Alloc>, _Alloc)
+    -> unordered_map<_Kty, _Ty, _STD hash<_Kty>, _STD equal_to<_Kty>, _Alloc>;
+
+template <class _Kty, class _Ty, class _Hasher, class _Alloc,
+    _STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD _Is_allocator<_Alloc>>, int> = 0>
+unordered_map(_STD initializer_list<_STD pair<_Kty, _Ty>>, _STD _Guide_size_type_t<_Alloc>, _Hasher, _Alloc)
+    -> unordered_map<_Kty, _Ty, _Hasher, _STD equal_to<_Kty>, _Alloc>;
+
+#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
+template <_RANGES input_range _Rng, class _Hasher = _STD hash<_Range_key_type<_Rng>>,
+    class _Keyeq = _STD equal_to<_Range_key_type<_Rng>>, class _Alloc = _STD allocator<_Range_to_alloc_type<_Rng>>,
+    _STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD negation<_STD _Is_allocator<_Keyeq>>, _STD _Is_allocator<_Alloc>>, int> = 0>
+unordered_map(from_range_t, _Rng&&, _STD _Guide_size_type_t<_Alloc> = 0, _Hasher = _Hasher(), _Keyeq = _Keyeq(),
+    _Alloc = _Alloc()) -> unordered_map<_Range_key_type<_Rng>, _Range_mapped_type<_Rng>, _Hasher, _Keyeq, _Alloc>;
+
+template <_RANGES input_range _Rng, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
+unordered_map(from_range_t, _Rng&&, _STD _Guide_size_type_t<_Alloc>, _Alloc) -> unordered_map<_Range_key_type<_Rng>,
+    _Range_mapped_type<_Rng>, _STD hash<_Range_key_type<_Rng>>, _STD equal_to<_Range_key_type<_Rng>>, _Alloc>;
+
+template <_RANGES input_range _Rng, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
+unordered_map(from_range_t, _Rng&&, _Alloc) -> unordered_map<_Range_key_type<_Rng>, _Range_mapped_type<_Rng>,
+    _STD hash<_Range_key_type<_Rng>>, _STD equal_to<_Range_key_type<_Rng>>, _Alloc>;
+
+template <_RANGES input_range _Rng, class _Hasher, class _Alloc,
+    _STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD _Is_allocator<_Alloc>>, int> = 0>
+unordered_map(from_range_t, _Rng&&, _STD _Guide_size_type_t<_Alloc>, _Hasher, _Alloc)
+    -> unordered_map<_Range_key_type<_Rng>, _Range_mapped_type<_Rng>, _Hasher, _STD equal_to<_Range_key_type<_Rng>>, _Alloc>;
+#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)
+#endif // _HAS_CXX17
+
+/*_EXPORT_STD*/ template <class _Kty, class _Ty, class _Hasher, class _Keyeq, class _Alloc>
+void swap(unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Left,
+    unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Right) noexcept(noexcept(_Left.swap(_Right))) {
+    _Left.swap(_Right);
+}
+
+#if _HAS_CXX20
+/*_EXPORT_STD*/ template <class _Kty, class _Ty, class _Hasher, class _Keyeq, class _Alloc, class _Pr>
+unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>::size_type erase_if(
+    unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Cont, _Pr _Pred) {
+    return _STD _Erase_nodes_if(_Cont, _STD _Pass_fn(_Pred));
+}
+#endif // _HAS_CXX20
+
+/*_EXPORT_STD*/ template <class _Kty, class _Ty, class _Hasher, class _Keyeq, class _Alloc>
+_NODISCARD bool operator==(const unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Left,
+    const unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Right) {
+    return ::geode::stl:: _Hash_equal(_Left, _Right);
+}
+
+#if !_HAS_CXX20
+template <class _Kty, class _Ty, class _Hasher, class _Keyeq, class _Alloc>
+_NODISCARD bool operator!=(const unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Left,
+    const unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Right) {
+    return !(_Left == _Right);
+}
+#endif // !_HAS_CXX20
+
+_STD_END
+#pragma pop_macro("new")
+_STL_RESTORE_CLANG_WARNINGS
+#pragma warning(pop)
+#pragma pack(pop)
+#endif // _STL_COMPILER_PREPROCESSOR
+#endif // _GEODE_UNORDERED_MAP_
diff --git a/loader/include/Geode/c++stl/msvc/uset.hpp b/loader/include/Geode/c++stl/msvc/uset.hpp
new file mode 100644
index 00000000..8e35e789
--- /dev/null
+++ b/loader/include/Geode/c++stl/msvc/uset.hpp
@@ -0,0 +1,417 @@
+// unordered_set standard header
+
+// Copyright (c) Microsoft Corporation.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// Per Apache License, Version 2.0, Section 4, Point b: I (kynex7510) changed this file.
+
+#ifndef _GEODE_UNORDERED_SET_
+#define _GEODE_UNORDERED_SET_
+#include <yvals_core.h>
+#if _STL_COMPILER_PREPROCESSOR
+#include "xhash.hpp"
+
+#if _HAS_CXX17
+#include <xpolymorphic_allocator.h>
+#endif // _HAS_CXX17
+
+#pragma pack(push, _CRT_PACKING)
+#pragma warning(push, _STL_WARNING_LEVEL)
+#pragma warning(disable : _STL_DISABLED_WARNINGS)
+_STL_DISABLE_CLANG_WARNINGS
+#pragma push_macro("new")
+#undef new
+
+namespace geode::stl {
+
+template <class _Kty, // key type (same as value type)
+    class _Tr, // comparator predicate type
+    class _Alloc, // actual allocator type (should be value allocator)
+    bool _Mfl> // true if multiple equivalent keys are permitted
+class _Uset_traits : public _Tr { // traits required to make _Hash behave like a set
+public:
+    using key_type            = _Kty;
+    using value_type          = _Kty;
+    using _Mutable_value_type = _Kty;
+    using key_compare         = _Tr;
+    using allocator_type      = _Alloc;
+#if _HAS_CXX17
+    using node_type = _STD _Node_handle<_STD _List_node<value_type, typename _STD allocator_traits<_Alloc>::void_pointer>, _Alloc,
+        _STD _Node_handle_set_base, _Kty>;
+#endif // _HAS_CXX17
+
+    static constexpr bool _Multi    = _Mfl;
+    static constexpr bool _Standard = true;
+
+    template <class... _Args>
+    using _In_place_key_extractor = _STD _In_place_key_extract_set<_Kty, _Args...>;
+
+    _Uset_traits() = default;
+
+    explicit _Uset_traits(const _Tr& _Traits) noexcept(_STD is_nothrow_copy_constructible_v<_Tr>) : _Tr(_Traits) {}
+
+    using value_compare = void; // TRANSITION, remove when _Standard becomes unconditionally true
+
+    static const _Kty& _Kfn(const value_type& _Val) noexcept {
+        return _Val;
+    }
+
+    static int _Nonkfn(const value_type&) noexcept { // extract "non-key" from element value (for container equality)
+        return 0;
+    }
+};
+
+/* _EXPORT_STD */ template <class _Kty, class _Hasher = _STD hash<_Kty>, class _Keyeq = _STD equal_to<_Kty>,
+    class _Alloc = allocator<_Kty>>
+class unordered_set : public _Hash<_Uset_traits<_Kty, _STD _Uhash_compare<_Kty, _Hasher, _Keyeq>, _Alloc, false>> {
+    // hash table of key-values, unique keys
+public:
+    static_assert(!_ENFORCE_MATCHING_ALLOCATORS || _STD is_same_v<_Kty, typename _Alloc::value_type>,
+        _MISMATCHED_ALLOCATOR_MESSAGE("unordered_set<T, Hasher, Eq, Allocator>", "T"));
+    static_assert(_STD is_object_v<_Kty>, "The C++ Standard forbids containers of non-object types "
+                                     "because of [container.requirements].");
+
+private:
+    using _Mytraits      = _STD _Uhash_compare<_Kty, _Hasher, _Keyeq>;
+    using _Mybase        = _Hash<_Uset_traits<_Kty, _Mytraits, _Alloc, false>>;
+    using _Alnode        = typename _Mybase::_Alnode;
+    using _Alnode_traits = typename _Mybase::_Alnode_traits;
+    using _Key_compare   = typename _Mybase::_Key_compare;
+
+public:
+    using hasher    = _Hasher;
+    using key_type  = _Kty;
+    using key_equal = _Keyeq;
+
+    using value_type      = typename _Mybase::value_type;
+    using allocator_type  = typename _Mybase::allocator_type;
+    using size_type       = typename _Mybase::size_type;
+    using difference_type = typename _Mybase::difference_type;
+    using pointer         = typename _Mybase::pointer;
+    using const_pointer   = typename _Mybase::const_pointer;
+    using reference       = value_type&;
+    using const_reference = const value_type&;
+    using iterator        = typename _Mybase::iterator;
+    using const_iterator  = typename _Mybase::const_iterator;
+
+    using local_iterator       = typename _Mybase::iterator;
+    using const_local_iterator = typename _Mybase::const_iterator;
+
+#if _HAS_CXX17
+    using insert_return_type = _STD _Insert_return_type<iterator, typename _Mybase::node_type>;
+#endif // _HAS_CXX17
+
+    unordered_set() : _Mybase(_Key_compare(), allocator_type()) {}
+
+    explicit unordered_set(const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {}
+
+    unordered_set(const unordered_set& _Right)
+        : _Mybase(_Right, _Alnode_traits::select_on_container_copy_construction(_Right._Getal())) {}
+
+    unordered_set(const unordered_set& _Right, const allocator_type& _Al) : _Mybase(_Right, _Al) {}
+
+    explicit unordered_set(size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
+        this->rehash(_Buckets);
+    }
+
+    unordered_set(size_type _Buckets, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
+        this->rehash(_Buckets);
+    }
+
+    unordered_set(size_type _Buckets, const hasher& _Hasharg) : _Mybase(_Key_compare(_Hasharg), allocator_type()) {
+        this->rehash(_Buckets);
+    }
+
+    unordered_set(size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg), _Al) {
+        this->rehash(_Buckets);
+    }
+
+    unordered_set(size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
+        this->rehash(_Buckets);
+    }
+
+    unordered_set(size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg, const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
+        this->rehash(_Buckets);
+    }
+
+    template <class _Iter>
+    unordered_set(_Iter _First, _Iter _Last) : _Mybase(_Key_compare(), allocator_type()) {
+        this->insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_set(_Iter _First, _Iter _Last, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
+        this->insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_set(_Iter _First, _Iter _Last, size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
+        this->rehash(_Buckets);
+        this->insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_set(_Iter _First, _Iter _Last, size_type _Buckets, const allocator_type& _Al)
+        : _Mybase(_Key_compare(), _Al) {
+        this->rehash(_Buckets);
+        this->insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_set(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg)
+        : _Mybase(_Key_compare(_Hasharg), allocator_type()) {
+        this->rehash(_Buckets);
+        this->insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_set(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg), _Al) {
+        this->rehash(_Buckets);
+        this->insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_set(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
+        this->rehash(_Buckets);
+        this->insert(_First, _Last);
+    }
+
+    template <class _Iter>
+    unordered_set(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg,
+        const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
+        this->rehash(_Buckets);
+        this->insert(_First, _Last);
+    }
+
+#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_set(from_range_t, _Rng&& _Range) : _Mybase(_Key_compare(), allocator_type()) {
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_set(from_range_t, _Rng&& _Range, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_set(from_range_t, _Rng&& _Range, size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_set(from_range_t, _Rng&& _Range, size_type _Buckets, const allocator_type& _Al)
+        : _Mybase(_Key_compare(), _Al) {
+        _Mybase::rehash(_Buckets);
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_set(from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg)
+        : _Mybase(_Key_compare(_Hasharg), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_set(from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg), _Al) {
+        _Mybase::rehash(_Buckets);
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_set(from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
+        _Mybase::rehash(_Buckets);
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+
+    template <_Container_compatible_range<value_type> _Rng>
+    unordered_set(from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg,
+        const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
+        _Mybase::rehash(_Buckets);
+        this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)
+
+    unordered_set& operator=(const unordered_set& _Right) {
+        _Mybase::operator=(_Right);
+        return *this;
+    }
+
+    unordered_set(unordered_set&& _Right) : _Mybase(_STD move(_Right)) {}
+
+    unordered_set(unordered_set&& _Right, const allocator_type& _Al) : _Mybase(_STD move(_Right), _Al) {}
+
+    unordered_set& operator=(unordered_set&& _Right) noexcept(_Alnode_traits::is_always_equal::value&&
+            _STD is_nothrow_move_assignable_v<_Hasher>&& _STD is_nothrow_move_assignable_v<_Keyeq>) {
+        _Mybase::operator=(_STD move(_Right));
+        return *this;
+    }
+
+    void swap(unordered_set& _Right) noexcept(noexcept(_Mybase::swap(_Right))) {
+        _Mybase::swap(_Right);
+    }
+
+    unordered_set(_STD initializer_list<value_type> _Ilist) : _Mybase(_Key_compare(), allocator_type()) {
+        this->insert(_Ilist);
+    }
+
+    unordered_set(_STD initializer_list<value_type> _Ilist, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
+        this->insert(_Ilist);
+    }
+
+    unordered_set(_STD initializer_list<value_type> _Ilist, size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
+        this->rehash(_Buckets);
+        this->insert(_Ilist);
+    }
+
+    unordered_set(_STD initializer_list<value_type> _Ilist, size_type _Buckets, const allocator_type& _Al)
+        : _Mybase(_Key_compare(), _Al) {
+        this->rehash(_Buckets);
+        this->insert(_Ilist);
+    }
+
+    unordered_set(_STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg)
+        : _Mybase(_Key_compare(_Hasharg), allocator_type()) {
+        this->rehash(_Buckets);
+        this->insert(_Ilist);
+    }
+
+    unordered_set(
+        _STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg), _Al) {
+        this->rehash(_Buckets);
+        this->insert(_Ilist);
+    }
+
+    unordered_set(
+        _STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
+        this->rehash(_Buckets);
+        this->insert(_Ilist);
+    }
+
+    unordered_set(_STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg,
+        const _Keyeq& _Keyeqarg, const allocator_type& _Al)
+        : _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
+        this->rehash(_Buckets);
+        this->insert(_Ilist);
+    }
+
+    unordered_set& operator=(_STD initializer_list<value_type> _Ilist) {
+        this->clear();
+        this->insert(_Ilist);
+        return *this;
+    }
+
+    _NODISCARD hasher hash_function() const {
+        return this->_Traitsobj._Mypair._Get_first();
+    }
+
+    _NODISCARD key_equal key_eq() const {
+        return this->_Traitsobj._Mypair._Myval2._Get_first();
+    }
+
+    using _Mybase::_Unchecked_begin;
+    using _Mybase::_Unchecked_end;
+};
+
+#if _HAS_CXX17
+template <class _Iter, class _Hasher = _STD hash<_STD _Iter_value_t<_Iter>>, class _Keyeq = _STD equal_to<_STD _Iter_value_t<_Iter>>,
+    class _Alloc = allocator<_STD _Iter_value_t<_Iter>>,
+    _STD enable_if_t<
+        _STD conjunction_v<_STD _Is_iterator<_Iter>, _Is_hasher<_Hasher>, _STD negation<_STD _Is_allocator<_Keyeq>>, _STD _Is_allocator<_Alloc>>,
+        int> = 0>
+unordered_set(_Iter, _Iter, _STD _Guide_size_type_t<_Alloc> = 0, _Hasher = _Hasher(), _Keyeq = _Keyeq(), _Alloc = _Alloc())
+    -> unordered_set<_STD _Iter_value_t<_Iter>, _Hasher, _Keyeq, _Alloc>;
+
+template <class _Kty, class _Hasher = _STD hash<_Kty>, class _Keyeq = _STD equal_to<_Kty>, class _Alloc = allocator<_Kty>,
+    _STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD negation<_STD _Is_allocator<_Keyeq>>, _STD _Is_allocator<_Alloc>>, int> = 0>
+unordered_set(_STD initializer_list<_Kty>, _STD _Guide_size_type_t<_Alloc> = 0, _Hasher = _Hasher(), _Keyeq = _Keyeq(),
+    _Alloc = _Alloc()) -> unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>;
+
+template <class _Iter, class _Alloc, _STD enable_if_t<_STD conjunction_v<_STD _Is_iterator<_Iter>, _STD _Is_allocator<_Alloc>>, int> = 0>
+unordered_set(_Iter, _Iter, _STD _Guide_size_type_t<_Alloc>, _Alloc)
+    -> unordered_set<_STD _Iter_value_t<_Iter>, _STD hash<_STD _Iter_value_t<_Iter>>, _STD equal_to<_STD _Iter_value_t<_Iter>>, _Alloc>;
+
+template <class _Iter, class _Hasher, class _Alloc,
+    _STD enable_if_t<_STD conjunction_v<_STD _Is_iterator<_Iter>, _Is_hasher<_Hasher>, _STD _Is_allocator<_Alloc>>, int> = 0>
+unordered_set(_Iter, _Iter, _STD _Guide_size_type_t<_Alloc>, _Hasher, _Alloc)
+    -> unordered_set<_STD _Iter_value_t<_Iter>, _Hasher, _STD equal_to<_STD _Iter_value_t<_Iter>>, _Alloc>;
+
+template <class _Kty, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
+unordered_set(_STD initializer_list<_Kty>, _STD _Guide_size_type_t<_Alloc>, _Alloc)
+    -> unordered_set<_Kty, _STD hash<_Kty>, _STD equal_to<_Kty>, _Alloc>;
+
+template <class _Kty, class _Hasher, class _Alloc,
+    _STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD _Is_allocator<_Alloc>>, int> = 0>
+unordered_set(_STD initializer_list<_Kty>, _STD _Guide_size_type_t<_Alloc>, _Hasher, _Alloc)
+    -> unordered_set<_Kty, _Hasher, _STD equal_to<_Kty>, _Alloc>;
+
+#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
+template <_RANGES input_range _Rng, class _Hasher = _STD hash<_RANGES range_value_t<_Rng>>,
+    class _Keyeq = _STD equal_to<_RANGES range_value_t<_Rng>>, class _Alloc = allocator<_RANGES range_value_t<_Rng>>,
+    _STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD negation<_STD _Is_allocator<_Keyeq>>, _STD _Is_allocator<_Alloc>>, int> = 0>
+unordered_set(from_range_t, _Rng&&, _STD _Guide_size_type_t<_Alloc> = 0, _Hasher = _Hasher(), _Keyeq = _Keyeq(),
+    _Alloc = _Alloc()) -> unordered_set<_RANGES range_value_t<_Rng>, _Hasher, _Keyeq, _Alloc>;
+
+template <_RANGES input_range _Rng, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
+unordered_set(from_range_t, _Rng&&, _STD _Guide_size_type_t<_Alloc>, _Alloc) -> unordered_set<_RANGES range_value_t<_Rng>,
+    _STD hash<_RANGES range_value_t<_Rng>>, _STD equal_to<_RANGES range_value_t<_Rng>>, _Alloc>;
+
+template <_RANGES input_range _Rng, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
+unordered_set(from_range_t, _Rng&&, _Alloc) -> unordered_set<_RANGES range_value_t<_Rng>,
+    _STD hash<_RANGES range_value_t<_Rng>>, _STD equal_to<_RANGES range_value_t<_Rng>>, _Alloc>;
+
+template <_RANGES input_range _Rng, class _Hasher, class _Alloc,
+    _STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD _Is_allocator<_Alloc>>, int> = 0>
+unordered_set(from_range_t, _Rng&&, _STD _Guide_size_type_t<_Alloc>, _Hasher, _Alloc)
+    -> unordered_set<_RANGES range_value_t<_Rng>, _Hasher, _STD equal_to<_RANGES range_value_t<_Rng>>, _Alloc>;
+#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)
+#endif // _HAS_CXX17
+
+/* _EXPORT_STD */ template <class _Kty, class _Hasher, class _Keyeq, class _Alloc>
+void swap(unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Left,
+    unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Right) noexcept(noexcept(_Left.swap(_Right))) {
+    _Left.swap(_Right);
+}
+
+#if _HAS_CXX20
+/* _EXPORT_STD */ template <class _Kty, class _Hasher, class _Keyeq, class _Alloc, class _Pr>
+unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>::size_type erase_if(
+    unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Cont, _Pr _Pred) {
+    return _STD _Erase_nodes_if(_Cont, _STD _Pass_fn(_Pred));
+}
+#endif // _HAS_CXX20
+
+/* _EXPORT_STD */ template <class _Kty, class _Hasher, class _Keyeq, class _Alloc>
+_NODISCARD bool operator==(const unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Left,
+    const unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Right) {
+    return geode::stl:: _Hash_equal(_Left, _Right);
+}
+
+#if !_HAS_CXX20
+template <class _Kty, class _Hasher, class _Keyeq, class _Alloc>
+_NODISCARD bool operator!=(const unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Left,
+    const unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Right) {
+    return !(_Left == _Right);
+}
+#endif // !_HAS_CXX20
+
+_STD_END
+#pragma pop_macro("new")
+_STL_RESTORE_CLANG_WARNINGS
+#pragma warning(pop)
+#pragma pack(pop)
+#endif // _STL_COMPILER_PREPROCESSOR
+#endif // _GEODE_UNORDERED_SET_
diff --git a/loader/include/Geode/c++stl/msvc/xhash.hpp b/loader/include/Geode/c++stl/msvc/xhash.hpp
new file mode 100644
index 00000000..85ee46c0
--- /dev/null
+++ b/loader/include/Geode/c++stl/msvc/xhash.hpp
@@ -0,0 +1,1793 @@
+// xhash internal header
+
+// Copyright (c) Microsoft Corporation.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// Per Apache License, Version 2.0, Section 4, Point b: I (kynex7510) changed this file.
+
+#ifndef _GEODE_XHASH_
+#define _GEODE_XHASH_
+#include <yvals_core.h>
+#if _STL_COMPILER_PREPROCESSOR
+#include <cmath>
+#include <list>
+#include <tuple>
+#include <vector>
+#include <xbit_ops.h>
+
+#ifdef _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
+#include <cstring>
+#include <cwchar>
+#include <xstring>
+#endif // _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
+
+#if _HAS_CXX17
+#include <xnode_handle.h>
+#endif // _HAS_CXX17
+
+#pragma pack(push, _CRT_PACKING)
+#pragma warning(push, _STL_WARNING_LEVEL)
+#pragma warning(disable : _STL_DISABLED_WARNINGS)
+_STL_DISABLE_CLANG_WARNINGS
+#pragma push_macro("new")
+#undef new
+
+// Include the original file for the required structs.
+#include <xhash>
+
+namespace geode::stl {
+
+using _STD _Fake_alloc;
+
+// The following types are not accessible from std::list.
+template <class _Ty, class _Alloc = _STD allocator<_Ty>>
+struct _ListImpl {
+    using _Mylist = _STD list<_Ty, _Alloc>;
+    using _Alty = _STD _Rebind_alloc_t<_Alloc, _Ty>;
+    using _Alty_traits = _STD allocator_traits<_Alty>;
+    using _Node = _STD _List_node<_Ty, typename _STD allocator_traits<_Alloc>::void_pointer>;
+    using _Alnode = _STD _Rebind_alloc_t<_Alloc, _Node>;
+    using _Alnode_traits = _STD allocator_traits<_Alnode>;
+    using _Nodeptr = typename _Alnode_traits::pointer;
+
+     using _Val_types = _STD conditional_t<_STD _Is_simple_alloc_v<_Alnode>, _STD _List_simple_types<_Ty>,
+        _STD _List_iter_types<_Ty, typename _Alty_traits::size_type, typename _Alty_traits::difference_type,
+            typename _Alty_traits::pointer, typename _Alty_traits::const_pointer, _Nodeptr>>;
+
+    using _Scary_val = _STD _List_val<_Val_types>;
+
+    using _PairType = _STD _Compressed_pair<_Alnode, _Scary_val>;
+
+    // These methods are required to bypass std::list visibility.
+
+    constexpr static size_t MYPAIR_OFFSET = 0;
+
+    static _PairType& _List_Mypair(_Mylist& _List) noexcept {
+        return *reinterpret_cast<_PairType*>(reinterpret_cast<uintptr_t>(&_List) + MYPAIR_OFFSET);
+    }
+
+    static const _PairType& _List_Mypair(const _Mylist& _List) noexcept {
+        return *reinterpret_cast<_PairType*>(reinterpret_cast<uintptr_t>(&_List) + MYPAIR_OFFSET);
+    }
+
+    static _Alnode& _List_Getal(_Mylist& _List) noexcept {
+        return _List_Mypair(_List)._Get_first();
+    }
+
+    static const _Alnode& _List_Getal(const _Mylist& _List) noexcept {
+        return _List_Mypair(_List)._Get_first();
+    }
+};
+
+template <class _Traits>
+class _Hash { // hash table -- list with vector of iterators for quick access
+protected:
+    using _MylistImpl         = typename _ListImpl<typename _Traits::value_type, typename _Traits::allocator_type>;
+    using _Mylist             = typename _MylistImpl::_Mylist;
+    using _Alnode             = typename /* _Mylist */ _MylistImpl::_Alnode;
+    using _Alnode_traits      = typename /* _Mylist */ _MylistImpl::_Alnode_traits;
+    using _Node               = typename /* _Mylist */ _MylistImpl::_Node;
+    using _Nodeptr            = typename /* _Mylist */ _MylistImpl::_Nodeptr;
+    using _Mutable_value_type = typename _Traits::_Mutable_value_type;
+
+    using _Key_compare   = typename _Traits::key_compare;
+    using _Value_compare = typename _Traits::value_compare;
+
+    typename _MylistImpl::_PairType& _List_Mypair() noexcept { return _MylistImpl::_List_Mypair(_List); }
+    const typename _MylistImpl::_PairType& _List_Mypair() const noexcept { return _MylistImpl::_List_Mypair(_List); }
+
+    _Alnode& _List_Getal() noexcept { return _MylistImpl::_List_Getal(_List); }
+    const _Alnode& _List_Getal() const noexcept { return _MylistImpl::_List_Getal(_List); }
+
+public:
+    using key_type = typename _Traits::key_type;
+
+    using value_type      = typename _Mylist::value_type;
+    using allocator_type  = typename _Mylist::allocator_type;
+    using size_type       = typename _Mylist::size_type;
+    using difference_type = typename _Mylist::difference_type;
+    using pointer         = typename _Mylist::pointer;
+    using const_pointer   = typename _Mylist::const_pointer;
+    using reference       = value_type&;
+    using const_reference = const value_type&;
+
+    using iterator =
+        _STD conditional_t<_STD is_same_v<key_type, value_type>, typename _Mylist::const_iterator, typename _Mylist::iterator>;
+    using const_iterator = typename _Mylist::const_iterator;
+
+    using _Unchecked_iterator       = _STD conditional_t<_STD is_same_v<key_type, value_type>,
+        typename _Mylist::_Unchecked_const_iterator, typename _Mylist::_Unchecked_iterator>;
+    using _Unchecked_const_iterator = typename _Mylist::_Unchecked_const_iterator;
+
+    using _Aliter = _STD _Rebind_alloc_t<_Alnode, _Unchecked_iterator>;
+
+    static constexpr size_type _Bucket_size = _Key_compare::bucket_size;
+    static constexpr size_type _Min_buckets = 8; // must be a positive power of 2
+    static constexpr bool _Multi            = _Traits::_Multi;
+
+    template <class _TraitsT>
+    friend bool _Hash_equal(const _Hash<_TraitsT>& _Left, const _Hash<_TraitsT>& _Right);
+
+protected:
+    _Hash(const _Key_compare& _Parg, const allocator_type& _Al)
+        : _Traitsobj(_Parg), _List(_Al), _Vec(_Al), _Mask(_Min_buckets - 1), _Maxidx(_Min_buckets) {
+        // construct empty hash table
+        _Max_bucket_size() = _Bucket_size;
+        _Vec._Assign_grow(_Min_buckets * 2, _List._Unchecked_end());
+#ifdef _ENABLE_STL_INTERNAL_CHECK
+        _Stl_internal_check_container_invariants();
+#endif // _ENABLE_STL_INTERNAL_CHECK
+    }
+
+    template <class _Any_alloc>
+    _Hash(const _Hash& _Right, const _Any_alloc& _Al)
+        : _Traitsobj(_Right._Traitsobj), _List(static_cast<allocator_type>(_Al)), _Vec(_Al), _Mask(_Right._Mask),
+          _Maxidx(_Right._Maxidx) {
+        // construct hash table by copying _Right
+        _Vec._Assign_grow(_Right._Vec.size(), _List._Unchecked_end());
+        _Insert_range_unchecked(_Right._Unchecked_begin(), _Right._Unchecked_end());
+#ifdef _ENABLE_STL_INTERNAL_CHECK
+        _Stl_internal_check_container_invariants();
+        _Right._Stl_internal_check_container_invariants();
+#endif // _ENABLE_STL_INTERNAL_CHECK
+    }
+
+    _Hash(_Hash&& _Right)
+        : _Traitsobj(_Right._Traitsobj), _List(_STD _Move_allocator_tag{}, _Right._List_Getal()),
+          _Vec(_STD move(_Right._Vec._Mypair._Get_first())) {
+        _Vec._Assign_grow(_Min_buckets * 2, _Unchecked_end());
+        _List._Swap_val(_Right._List);
+        _Vec._Mypair._Myval2._Swap_val(_Right._Vec._Mypair._Myval2);
+        _Mask   = _STD exchange(_Right._Mask, _Min_buckets - 1);
+        _Maxidx = _STD exchange(_Right._Maxidx, _Min_buckets);
+#ifdef _ENABLE_STL_INTERNAL_CHECK
+        _Stl_internal_check_container_invariants();
+        _Right._Stl_internal_check_container_invariants();
+#endif // _ENABLE_STL_INTERNAL_CHECK
+    }
+
+private:
+    void _Move_construct_equal_alloc(_Hash& _Right) {
+        _Vec._Assign_grow(_Min_buckets * 2, _Unchecked_end());
+        _List._Swap_val(_Right._List);
+        _Vec._Mypair._Myval2._Swap_val(_Right._Vec._Mypair._Myval2);
+        _Mask   = _STD exchange(_Right._Mask, _Min_buckets - 1);
+        _Maxidx = _STD exchange(_Right._Maxidx, _Min_buckets);
+    }
+
+public:
+    _Hash(_Hash&& _Right, const allocator_type& _Al) : _Traitsobj(_Right._Traitsobj), _List(_Al), _Vec(_Al) {
+        // construct hash table by moving _Right, allocator
+        if constexpr (_Alnode_traits::is_always_equal::value) {
+            _Move_construct_equal_alloc(_Right);
+        } else if (_List_Getal() == _Right._List_Getal()) {
+            _Move_construct_equal_alloc(_Right);
+        } else {
+            _Maxidx            = _Min_buckets;
+            const auto _Myhead = _List_Mypair()._Myval2._Myhead;
+            for (auto& _Val : _Right._List) {
+                _List._Emplace(_Myhead, reinterpret_cast<_Mutable_value_type&&>(_Val));
+            }
+            _Reinsert_with_invalid_vec();
+            _Right.clear();
+        }
+
+#ifdef _ENABLE_STL_INTERNAL_CHECK
+        _Stl_internal_check_container_invariants();
+        _Right._Stl_internal_check_container_invariants();
+#endif // _ENABLE_STL_INTERNAL_CHECK
+    }
+
+private:
+    void _Swap_val(_Hash& _Right) noexcept { // swap contents with equal allocator _Hash _Right
+        _List._Swap_val(_Right._List);
+        _Vec._Mypair._Myval2._Swap_val(_Right._Vec._Mypair._Myval2);
+        _STD swap(_Mask, _Right._Mask);
+        _STD swap(_Maxidx, _Right._Maxidx);
+    }
+
+    struct _Min_buckets_construct_ptr {
+        using pointer = typename _STD allocator_traits<_Aliter>::pointer;
+        _Aliter& _Al;
+        pointer _Base;
+        _Min_buckets_construct_ptr(_Aliter& _Al_) : _Al(_Al_), _Base(_Al.allocate(_Min_buckets * 2)) {}
+        _Min_buckets_construct_ptr(const _Min_buckets_construct_ptr&) = delete;
+        _NODISCARD pointer _Release(_Unchecked_iterator _Newend) noexcept {
+            _STD uninitialized_fill(_Base, _Base + _Min_buckets * 2, _Newend);
+            return _STD exchange(_Base, nullptr);
+        }
+        ~_Min_buckets_construct_ptr() {
+            if (_Base) {
+                _Al.deallocate(_Base, _Min_buckets * 2);
+            }
+        }
+    };
+
+    void _Pocma_both(_Hash& _Right) {
+        _Pocma(_List_Getal(), _Right._List_Getal());
+        _Pocma(_Vec._Mypair._Get_first(), _Right._Vec._Mypair._Get_first());
+    }
+
+    struct _NODISCARD _Clear_guard {
+        _Hash* _Target;
+
+        explicit _Clear_guard(_Hash* const _Target_) : _Target(_Target_) {}
+
+        _Clear_guard(const _Clear_guard&)            = delete;
+        _Clear_guard& operator=(const _Clear_guard&) = delete;
+
+        ~_Clear_guard() {
+            if (_Target) {
+                _Target->clear();
+            }
+        }
+    };
+
+#ifdef _ENABLE_STL_INTERNAL_CHECK
+    struct _NODISCARD _Check_container_invariants_guard {
+        const _Hash& _Target;
+
+        explicit _Check_container_invariants_guard(const _Hash& _Target_) : _Target(_Target_) {}
+
+        _Check_container_invariants_guard(const _Check_container_invariants_guard&)            = delete;
+        _Check_container_invariants_guard& operator=(const _Check_container_invariants_guard&) = delete;
+
+        ~_Check_container_invariants_guard() {
+            _Target._Stl_internal_check_container_invariants();
+        }
+    };
+#endif // _ENABLE_STL_INTERNAL_CHECK
+
+public:
+    _Hash& operator=(_Hash&& _Right) { // assign by moving _Right
+        if (this == _STD addressof(_Right)) {
+            return *this;
+        }
+
+#ifdef _ENABLE_STL_INTERNAL_CHECK
+        _Check_container_invariants_guard _Check_self{*this};
+        _Check_container_invariants_guard _Check_right{_Right};
+#endif // _ENABLE_STL_INTERNAL_CHECK
+
+        auto& _Al                 = _Getal();
+        auto& _Right_al           = _Right._Getal();
+        constexpr auto _Pocma_val = _STD _Choose_pocma_v<_Alnode>;
+        if constexpr (_Pocma_val == _STD _Pocma_values::_Propagate_allocators) {
+            if (_Al != _Right_al) {
+                // allocate all the parts necessary to maintain _Hash invariants using _Right's allocator
+                auto&& _Alproxy       = _GET_PROXY_ALLOCATOR(_Alnode, _Al);
+                auto&& _Right_alproxy = _GET_PROXY_ALLOCATOR(_Alnode, _Right_al);
+                _STD _Container_proxy_ptr<_Alnode> _List_proxy(_Right_alproxy, _STD _Leave_proxy_unbound{});
+                _STD _Container_proxy_ptr<_Alnode> _Vec_proxy(_Right_alproxy, _STD _Leave_proxy_unbound{});
+                _STD _List_head_construct_ptr<_Alnode> _Newhead(_Right_al);
+                _Min_buckets_construct_ptr _Buckets(_Right._Vec._Mypair._Get_first());
+
+                // assign the hash/compare ops; we have no control over whether this throws, and if it does we want
+                // to do nothing
+                _Traitsobj = _Right._Traitsobj;
+
+                // nothrow hereafter
+
+                // release any state we are currently owning, and propagate the allocators
+                _List._Tidy();
+                _Vec._Tidy();
+                _Pocma_both(_Right);
+
+                // assign the empty list to _Right._List (except the allocators), and take _Right's _List data
+                auto& _List_data       = _List_Mypair()._Myval2;
+                auto& _Right_list_data = _Right._List_Mypair()._Myval2;
+                _List_data._Myhead     = _STD exchange(_Right_list_data._Myhead, _Newhead._Release());
+                _List_data._Mysize     = _STD exchange(_Right_list_data._Mysize, size_type{0});
+                _List_proxy._Bind(_Alproxy, _STD addressof(_List_data));
+                _List_data._Swap_proxy_and_iterators(_Right_list_data);
+
+                // assign the _Min_buckets into _Right's _Vec data and take _Right's _Vec data
+                auto& _Vec_data       = _Vec._Mypair._Myval2;
+                auto& _Right_vec_data = _Right._Vec._Mypair._Myval2;
+
+                const auto _Newfirst = _Buckets._Release(_Right._Unchecked_end());
+                const auto _Newlast  = _Newfirst + _Min_buckets * 2;
+
+                _Vec_data._Myfirst = _STD exchange(_Right_vec_data._Myfirst, _Newfirst);
+                _Vec_data._Mylast  = _STD exchange(_Right_vec_data._Mylast, _Newlast);
+                _Vec_data._Myend   = _STD exchange(_Right_vec_data._Myend, _Newlast);
+                _Vec_proxy._Bind(_Alproxy, _STD addressof(_Vec_data));
+                _Vec_data._Swap_proxy_and_iterators(_Right_vec_data);
+
+                // give _Right the default _Mask and _Maxidx values and take its former values
+                _Mask   = _STD exchange(_Right._Mask, _Min_buckets - 1);
+                _Maxidx = _STD exchange(_Right._Maxidx, _Min_buckets);
+
+                return *this;
+            }
+        } else if constexpr (_Pocma_val == _STD _Pocma_values::_No_propagate_allocators) {
+            if (_Al != _Right_al) {
+                _Clear_guard _Guard{this};
+                _Traitsobj     = _Right._Traitsobj;
+                using _Adapter = _STD _Reinterpret_move_iter<typename _Mylist::_Unchecked_iterator, _Mutable_value_type>;
+                _List.template _Assign_cast<_Mutable_value_type&>(
+                    _Adapter{_Right._List._Unchecked_begin()}, _Adapter{_Right._List._Unchecked_end()});
+                _Reinsert_with_invalid_vec();
+                _Guard._Target = nullptr;
+
+                return *this;
+            }
+        }
+
+        clear();
+        _Traitsobj = _Right._Traitsobj;
+        _Pocma_both(_Right);
+        _Swap_val(_Right);
+
+        return *this;
+    }
+
+    template <class... _Valtys>
+    _STD conditional_t<_Multi, iterator, _STD pair<iterator, bool>> emplace(_Valtys&&... _Vals) {
+        // try to insert value_type(_Vals...)
+        using _In_place_key_extractor = typename _Traits::template _In_place_key_extractor<_STD _Remove_cvref_t<_Valtys>...>;
+        if constexpr (_Multi) {
+            _Check_max_size();
+            _STD _List_node_emplace_op2<_Alnode> _Newnode(_List_Getal(), _STD forward<_Valtys>(_Vals)...);
+            const auto& _Keyval = _Traits::_Kfn(_Newnode._Ptr->_Myval);
+            const auto _Hashval = _Traitsobj(_Keyval);
+            if (_Check_rehash_required_1()) {
+                _Rehash_for_1();
+            }
+
+            const auto _Target = _Find_last(_Keyval, _Hashval);
+            return _List._Make_iter(_Insert_new_node_before(_Hashval, _Target._Insert_before, _Newnode._Release()));
+        } else if constexpr (_In_place_key_extractor::_Extractable) {
+            const auto& _Keyval = _In_place_key_extractor::_Extract(_Vals...);
+            const auto _Hashval = _Traitsobj(_Keyval);
+            auto _Target        = _Find_last(_Keyval, _Hashval);
+            if (_Target._Duplicate) {
+                return {_List._Make_iter(_Target._Duplicate), false};
+            }
+
+            _Check_max_size();
+            // invalidates _Keyval:
+            _STD _List_node_emplace_op2<_Alnode> _Newnode(_List_Getal(), _STD forward<_Valtys>(_Vals)...);
+            if (_Check_rehash_required_1()) {
+                _Rehash_for_1();
+                _Target = _Find_last(_Traits::_Kfn(_Newnode._Ptr->_Myval), _Hashval);
+            }
+
+            return {
+                _List._Make_iter(_Insert_new_node_before(_Hashval, _Target._Insert_before, _Newnode._Release())), true};
+        } else {
+            _STD _List_node_emplace_op2<_Alnode> _Newnode(_List_Getal(), _STD forward<_Valtys>(_Vals)...);
+            const auto& _Keyval = _Traits::_Kfn(_Newnode._Ptr->_Myval);
+            const auto _Hashval = _Traitsobj(_Keyval);
+            auto _Target        = _Find_last(_Keyval, _Hashval);
+            if (_Target._Duplicate) {
+                return {_List._Make_iter(_Target._Duplicate), false};
+            }
+
+            _Check_max_size();
+            if (_Check_rehash_required_1()) {
+                _Rehash_for_1();
+                _Target = _Find_last(_Traits::_Kfn(_Newnode._Ptr->_Myval), _Hashval);
+            }
+
+            return {
+                _List._Make_iter(_Insert_new_node_before(_Hashval, _Target._Insert_before, _Newnode._Release())), true};
+        }
+    }
+
+    template <class... _Valtys>
+    iterator emplace_hint(const_iterator _Hint, _Valtys&&... _Vals) { // try to insert value_type(_Vals...)
+        using _In_place_key_extractor = typename _Traits::template _In_place_key_extractor<_STD _Remove_cvref_t<_Valtys>...>;
+        if constexpr (_Multi) {
+            _Check_max_size();
+            _STD _List_node_emplace_op2<_Alnode> _Newnode(_List_Getal(), _STD forward<_Valtys>(_Vals)...);
+            const auto& _Keyval = _Traits::_Kfn(_Newnode._Ptr->_Myval);
+            const auto _Hashval = _Traitsobj(_Keyval);
+            if (_Check_rehash_required_1()) {
+                _Rehash_for_1();
+            }
+
+            const auto _Target = _Find_hint(_Hint._Ptr, _Keyval, _Hashval);
+            return _List._Make_iter(_Insert_new_node_before(_Hashval, _Target._Insert_before, _Newnode._Release()));
+        } else if constexpr (_In_place_key_extractor::_Extractable) {
+            const auto& _Keyval = _In_place_key_extractor::_Extract(_Vals...);
+            const auto _Hashval = _Traitsobj(_Keyval);
+            auto _Target        = _Find_hint(_Hint._Ptr, _Keyval, _Hashval);
+            if (_Target._Duplicate) {
+                return _List._Make_iter(_Target._Duplicate);
+            }
+
+            _Check_max_size();
+            // invalidates _Keyval:
+            _STD _List_node_emplace_op2<_Alnode> _Newnode(_List_Getal(), _STD forward<_Valtys>(_Vals)...);
+            if (_Check_rehash_required_1()) {
+                _Rehash_for_1();
+                _Target = _Find_hint(_Hint._Ptr, _Traits::_Kfn(_Newnode._Ptr->_Myval), _Hashval);
+            }
+
+            return _List._Make_iter(_Insert_new_node_before(_Hashval, _Target._Insert_before, _Newnode._Release()));
+        } else {
+            _STD _List_node_emplace_op2<_Alnode> _Newnode(_List_Getal(), _STD forward<_Valtys>(_Vals)...);
+            const auto& _Keyval = _Traits::_Kfn(_Newnode._Ptr->_Myval);
+            const auto _Hashval = _Traitsobj(_Keyval);
+            auto _Target        = _Find_hint(_Hint._Ptr, _Keyval, _Hashval);
+            if (_Target._Duplicate) {
+                return _List._Make_iter(_Target._Duplicate);
+            }
+
+            _Check_max_size();
+            if (_Check_rehash_required_1()) {
+                _Rehash_for_1();
+                _Target = _Find_hint(_Hint._Ptr, _Traits::_Kfn(_Newnode._Ptr->_Myval), _Hashval);
+            }
+
+            return _List._Make_iter(_Insert_new_node_before(_Hashval, _Target._Insert_before, _Newnode._Release()));
+        }
+    }
+
+protected:
+    template <class _Keyty, class... _Mappedty>
+    _STD pair<_Nodeptr, bool> _Try_emplace(_Keyty&& _Keyval_arg, _Mappedty&&... _Mapval) {
+        const auto& _Keyval = _Keyval_arg;
+        const auto _Hashval = _Traitsobj(_Keyval);
+        auto _Target        = _Find_last(_Keyval, _Hashval);
+        if (_Target._Duplicate) {
+            return {_Target._Duplicate, false};
+        }
+
+        _Check_max_size();
+        _STD _List_node_emplace_op2<_Alnode> _Newnode(_List_Getal(), _STD piecewise_construct,
+            _STD forward_as_tuple(_STD forward<_Keyty>(_Keyval_arg)),
+            _STD forward_as_tuple(_STD forward<_Mappedty>(_Mapval)...));
+        if (_Check_rehash_required_1()) {
+            _Rehash_for_1();
+            _Target = _Find_last(_Traits::_Kfn(_Newnode._Ptr->_Myval), _Hashval);
+        }
+
+        return {_Insert_new_node_before(_Hashval, _Target._Insert_before, _Newnode._Release()), true};
+    }
+
+    template <class _Keyty, class... _Mappedty>
+    _Nodeptr _Try_emplace_hint(const _Nodeptr _Hint, _Keyty&& _Keyval_arg, _Mappedty&&... _Mapval) {
+        const auto& _Keyval = _Keyval_arg;
+        const auto _Hashval = _Traitsobj(_Keyval);
+        auto _Target        = _Find_hint(_Hint, _Keyval, _Hashval);
+        if (_Target._Duplicate) {
+            return _Target._Duplicate;
+        }
+
+        _Check_max_size();
+        // might invalidate _Keyval:
+        _STD _List_node_emplace_op2<_Alnode> _Newnode(_List_Getal(), _STD piecewise_construct,
+            _STD forward_as_tuple(_STD forward<_Keyty>(_Keyval_arg)),
+            _STD forward_as_tuple(_STD forward<_Mappedty>(_Mapval)...));
+        if (_Check_rehash_required_1()) {
+            _Rehash_for_1();
+            _Target = _Find_hint(_Hint, _Traits::_Kfn(_Newnode._Ptr->_Myval), _Hashval);
+        }
+
+        return _Insert_new_node_before(_Hashval, _Target._Insert_before, _Newnode._Release());
+    }
+
+private:
+    void _Pocca_both(const _Hash& _Right) {
+        _Pocca(_List_Getal(), _Right._List_Getal());
+        _Pocca(_Vec._Mypair._Get_first(), _Right._Vec._Mypair._Get_first());
+    }
+
+public:
+    _Hash& operator=(const _Hash& _Right) {
+        if (this == _STD addressof(_Right)) {
+            return *this;
+        }
+
+#ifdef _ENABLE_STL_INTERNAL_CHECK
+        _Check_container_invariants_guard _Check_self{*this};
+        _Check_container_invariants_guard _Check_right{_Right};
+#endif // _ENABLE_STL_INTERNAL_CHECK
+
+        if constexpr (_STD _Choose_pocca_v<_Alnode>) {
+            auto& _Al             = _Getal();
+            const auto& _Right_al = _Right._Getal();
+            if (_Al != _Right_al) {
+                auto&& _Alproxy       = _GET_PROXY_ALLOCATOR(_Alnode, _Al);
+                auto&& _Right_alproxy = _GET_PROXY_ALLOCATOR(_Alnode, _Right_al);
+                _STD _Container_proxy_ptr<_Alnode> _Vec_proxy(_Right_alproxy, _STD _Leave_proxy_unbound{});
+                _List._Reload_sentinel_and_proxy(_Right._List);
+                _Vec._Tidy();
+                _Pocca_both(_Right);
+                _Vec_proxy._Bind(_Alproxy, _STD addressof(_Vec._Mypair._Myval2));
+
+                _Clear_guard _Guard{this};
+                _Traitsobj = _Right._Traitsobj;
+                _List.template _Assign_cast<_Mutable_value_type&>(
+                    _Right._List._Unchecked_begin(), _Right._List._Unchecked_end());
+                _Reinsert_with_invalid_vec();
+                _Guard._Target = nullptr;
+
+                return *this;
+            }
+        }
+
+        _Clear_guard _Guard{this};
+        _Traitsobj = _Right._Traitsobj;
+        _Pocca_both(_Right);
+        _List.template _Assign_cast<_Mutable_value_type&>(
+            _Right._List._Unchecked_begin(), _Right._List._Unchecked_end());
+        _Reinsert_with_invalid_vec();
+        _Guard._Target = nullptr;
+
+        return *this;
+    }
+
+    _NODISCARD iterator begin() noexcept {
+        return _List.begin();
+    }
+
+    _NODISCARD const_iterator begin() const noexcept {
+        return _List.begin();
+    }
+
+    _NODISCARD iterator end() noexcept {
+        return _List.end();
+    }
+
+    _NODISCARD const_iterator end() const noexcept {
+        return _List.end();
+    }
+
+    _Unchecked_iterator _Unchecked_begin() noexcept {
+        return _List._Unchecked_begin();
+    }
+
+    _Unchecked_const_iterator _Unchecked_begin() const noexcept {
+        return _List._Unchecked_begin();
+    }
+
+    _Unchecked_iterator _Unchecked_end() noexcept {
+        return _List._Unchecked_end();
+    }
+
+    _Unchecked_const_iterator _Unchecked_end() const noexcept {
+        return _List._Unchecked_end();
+    }
+
+    _NODISCARD const_iterator cbegin() const noexcept {
+        return begin();
+    }
+
+    _NODISCARD const_iterator cend() const noexcept {
+        return end();
+    }
+
+    _NODISCARD size_type size() const noexcept {
+        return _List.size();
+    }
+
+    _NODISCARD size_type max_size() const noexcept {
+        return _List.max_size();
+    }
+
+    _NODISCARD_EMPTY_MEMBER bool empty() const noexcept {
+        return _List.empty();
+    }
+
+    _NODISCARD allocator_type get_allocator() const noexcept {
+        return static_cast<allocator_type>(_List.get_allocator());
+    }
+
+    using local_iterator       = iterator;
+    using const_local_iterator = const_iterator;
+
+    _NODISCARD size_type bucket_count() const noexcept {
+        return _Maxidx;
+    }
+
+    _NODISCARD size_type max_bucket_count() const noexcept {
+        return _Vec.max_size() >> 1;
+    }
+
+    _NODISCARD size_type bucket(const key_type& _Keyval) const
+        noexcept(_STD _Nothrow_hash<_Traits, key_type>) /* strengthened */ {
+        return _Traitsobj(_Keyval) & _Mask;
+    }
+
+    _NODISCARD size_type bucket_size(size_type _Bucket) const noexcept /* strengthened */ {
+        _Unchecked_iterator _Bucket_lo = _Vec._Mypair._Myval2._Myfirst[_Bucket << 1];
+        if (_Bucket_lo == _Unchecked_end()) {
+            return 0;
+        }
+
+        return static_cast<size_type>(_STD distance(_Bucket_lo, _Vec._Mypair._Myval2._Myfirst[(_Bucket << 1) + 1])) + 1;
+    }
+
+    _NODISCARD local_iterator begin(size_type _Bucket) noexcept /* strengthened */ {
+        return _List._Make_iter(_Vec._Mypair._Myval2._Myfirst[_Bucket << 1]._Ptr);
+    }
+
+    _NODISCARD const_local_iterator begin(size_type _Bucket) const noexcept /* strengthened */ {
+        return _List._Make_const_iter(_Vec._Mypair._Myval2._Myfirst[_Bucket << 1]._Ptr);
+    }
+
+    _NODISCARD local_iterator end(size_type _Bucket) noexcept /* strengthened */ {
+        _Nodeptr _Bucket_hi = _Vec._Mypair._Myval2._Myfirst[(_Bucket << 1) + 1]._Ptr;
+        if (_Bucket_hi != _List_Mypair()._Myval2._Myhead) {
+            _Bucket_hi = _Bucket_hi->_Next;
+        }
+
+        return _List._Make_iter(_Bucket_hi);
+    }
+
+    _NODISCARD const_local_iterator end(size_type _Bucket) const noexcept /* strengthened */ {
+        _Nodeptr _Bucket_hi = _Vec._Mypair._Myval2._Myfirst[(_Bucket << 1) + 1]._Ptr;
+        if (_Bucket_hi != _List_Mypair()._Myval2._Myhead) {
+            _Bucket_hi = _Bucket_hi->_Next;
+        }
+
+        return _List._Make_const_iter(_Bucket_hi);
+    }
+
+    _NODISCARD const_local_iterator cbegin(size_type _Bucket) const noexcept /* strengthened */ {
+        return _List._Make_const_iter(_Vec._Mypair._Myval2._Myfirst[_Bucket << 1]._Ptr);
+    }
+
+    _NODISCARD const_local_iterator cend(size_type _Bucket) const noexcept /* strengthened */ {
+        _Nodeptr _Bucket_hi = _Vec._Mypair._Myval2._Myfirst[(_Bucket << 1) + 1]._Ptr;
+        if (_Bucket_hi != _List_Mypair()._Myval2._Myhead) {
+            _Bucket_hi = _Bucket_hi->_Next;
+        }
+
+        return _List._Make_const_iter(_Bucket_hi);
+    }
+
+    _NODISCARD float load_factor() const noexcept {
+        return static_cast<float>(size()) / static_cast<float>(bucket_count());
+    }
+
+    _NODISCARD float max_load_factor() const noexcept {
+        return _Max_bucket_size();
+    }
+
+    void max_load_factor(float _Newmax) noexcept /* strengthened */ {
+        _STL_ASSERT(!(_CSTD isnan)(_Newmax) && _Newmax > 0, "invalid hash load factor");
+        _Max_bucket_size() = _Newmax;
+    }
+
+    void rehash(size_type _Buckets) { // rebuild table with at least _Buckets buckets
+        // don't violate a.bucket_count() >= a.size() / a.max_load_factor() invariant:
+        _Buckets = (_STD max)(_Min_load_factor_buckets(_List.size()), _Buckets);
+        if (_Buckets <= _Maxidx) { // we already have enough buckets; nothing to do
+            return;
+        }
+
+        _Forced_rehash(_Buckets);
+    }
+
+    void reserve(size_type _Maxcount) { // rebuild table with room for _Maxcount elements
+        rehash(_Min_load_factor_buckets(_Maxcount));
+    }
+
+    _STD conditional_t<_Multi, iterator, _STD pair<iterator, bool>> insert(const value_type& _Val) {
+        return emplace(_Val);
+    }
+
+    _STD conditional_t<_Multi, iterator, _STD pair<iterator, bool>> insert(value_type&& _Val) {
+        return emplace(_STD move(_Val));
+    }
+
+    iterator insert(const_iterator _Hint, const value_type& _Val) {
+        return emplace_hint(_Hint, _Val);
+    }
+
+    iterator insert(const_iterator _Hint, value_type&& _Val) {
+        return emplace_hint(_Hint, _STD move(_Val));
+    }
+
+protected:
+    template <class _Iter, class _Sent>
+    void _Insert_range_unchecked(_Iter _First, const _Sent _Last) {
+        for (; _First != _Last; ++_First) {
+            emplace(*_First);
+        }
+    }
+
+public:
+    template <class _Iter>
+    void insert(_Iter _First, _Iter _Last) {
+        _STD _Adl_verify_range(_First, _Last);
+        _Insert_range_unchecked(_Get_unwrapped(_First), _Get_unwrapped(_Last));
+    }
+
+#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
+    template <_Container_compatible_range<value_type> _Rng>
+    void insert_range(_Rng&& _Range) {
+        _Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
+    }
+#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)
+
+    void insert(_STD initializer_list<value_type> _Ilist) {
+        _Insert_range_unchecked(_Ilist.begin(), _Ilist.end());
+    }
+
+private:
+    _Nodeptr _Unchecked_erase(_Nodeptr _Plist) noexcept(_STD _Nothrow_hash<_Traits, key_type>) {
+        size_type _Bucket = bucket(_Traits::_Kfn(_Plist->_Myval));
+        _Erase_bucket(_Plist, _Bucket);
+        return _List._Unchecked_erase(_Plist);
+    }
+
+    struct _Range_eraser {
+        _Range_eraser(const _Range_eraser&)            = delete;
+        _Range_eraser& operator=(const _Range_eraser&) = delete;
+
+#if _ITERATOR_DEBUG_LEVEL == 2
+        // Keep the list nodes around until we have found all those we will erase, for an O(iterators + erasures) update
+        // of the iterator chain.
+        _Range_eraser(_Mylist& _List_, const _Nodeptr _First_) noexcept
+            : _List(_List_), _First(_First_), _Next(_First_) {}
+
+        void _Bump_erased() noexcept {
+            _Next = _Next->_Next;
+        }
+
+        ~_Range_eraser() noexcept {
+            _List._Unchecked_erase(_First, _Next);
+        }
+
+        _Mylist& _List;
+        const _Nodeptr _First;
+        _Nodeptr _Next;
+#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL != 2 vvv
+      // Destroy the nodes as we encounter them to avoid a second traversal of the linked list.
+        _Range_eraser(_Mylist& _List_, const _Nodeptr _First_) noexcept
+            : _List(_List_), _Predecessor(_First_->_Prev), _Next(_First_) {}
+
+        void _Bump_erased() noexcept {
+            const auto _Oldnext = _Next;
+            _Next               = _Oldnext->_Next;
+            _Node::_Freenode(_MylistImpl::_List_Getal(_List), _Oldnext);
+            --_MylistImpl::_List_Mypair(_List)._Myval2._Mysize;
+        }
+
+        ~_Range_eraser() noexcept {
+            _Predecessor->_Next = _Next;
+            _Next->_Prev        = _Predecessor;
+        }
+
+        _Mylist& _List;
+        const _Nodeptr _Predecessor;
+        _Nodeptr _Next;
+#endif
+    };
+
+    _Nodeptr _Unchecked_erase(_Nodeptr _First, const _Nodeptr _Last) noexcept(_STD _Nothrow_hash<_Traits, key_type>) {
+        if (_First == _Last) {
+            return _Last;
+        }
+
+        const auto _End           = _List_Mypair()._Myval2._Myhead;
+        const auto _Bucket_bounds = _Vec._Mypair._Myval2._Myfirst;
+        _Range_eraser _Eraser{_List, _First};
+        {
+            // process the first bucket, which is special because here _First might not be the beginning of the bucket
+            const auto _Predecessor = _First->_Prev;
+            const size_type _Bucket = bucket(_Traits::_Kfn(_Eraser._Next->_Myval)); // throws
+            // nothrow hereafter this block
+            _Nodeptr& _Bucket_lo   = _Bucket_bounds[_Bucket << 1]._Ptr;
+            _Nodeptr& _Bucket_hi   = _Bucket_bounds[(_Bucket << 1) + 1]._Ptr;
+            const bool _Update_lo  = _Bucket_lo == _Eraser._Next;
+            const _Nodeptr _Old_hi = _Bucket_hi;
+            for (;;) { // remove elements until we hit the end of the bucket
+                const bool _At_bucket_back = _Eraser._Next == _Old_hi;
+                _Eraser._Bump_erased();
+                if (_At_bucket_back) {
+                    break;
+                }
+
+                if (_Eraser._Next == _Last) {
+                    if (_Update_lo) {
+                        // erased the bucket's prefix
+                        _Bucket_lo = _Eraser._Next;
+                    }
+
+                    return _Last;
+                }
+            }
+
+            if (_Update_lo) {
+                // emptied the bucket
+                _Bucket_lo = _End;
+                _Bucket_hi = _End;
+            } else {
+                _Bucket_hi = _Predecessor;
+            }
+        }
+
+        // hereafter we are always erasing buckets' prefixes
+        while (_Eraser._Next != _Last) {
+            const size_type _Bucket = bucket(_Traits::_Kfn(_Eraser._Next->_Myval)); // throws
+            // nothrow hereafter this block
+            _Nodeptr& _Bucket_lo   = _Bucket_bounds[_Bucket << 1]._Ptr;
+            _Nodeptr& _Bucket_hi   = _Bucket_bounds[(_Bucket << 1) + 1]._Ptr;
+            const _Nodeptr _Old_hi = _Bucket_hi;
+            for (;;) { // remove elements until we hit the end of the bucket
+                const bool _At_bucket_back = _Eraser._Next == _Old_hi;
+                _Eraser._Bump_erased();
+                if (_At_bucket_back) {
+                    break;
+                }
+
+                if (_Eraser._Next == _Last) {
+                    // erased the bucket's prefix
+                    _Bucket_lo = _Eraser._Next;
+                    return _Last;
+                }
+            }
+
+            // emptied the bucket
+            _Bucket_lo = _End;
+            _Bucket_hi = _End;
+        }
+
+        return _Last;
+    }
+
+    template <class _Kx>
+    static constexpr bool _Noexcept_heterogeneous_erasure() {
+        return _STD _Nothrow_hash<_Traits, _Kx>
+            && (!_Multi || (_STD _Nothrow_compare<_Traits, key_type, _Kx> && _STD _Nothrow_compare<_Traits, _Kx, key_type>) );
+    }
+
+    template <class _Keytype>
+    size_type _Erase(const _Keytype& _Keyval) noexcept(_Noexcept_heterogeneous_erasure<_Keytype>()) /* strengthened */ {
+        const size_t _Hashval = _Traitsobj(_Keyval);
+        if constexpr (_Multi) {
+            const auto _Where = _Equal_range(_Keyval, _Hashval);
+            _Unchecked_erase(_Where._First._Ptr, _Where._Last._Ptr);
+            return _Where._Distance;
+        } else {
+            const auto _Target = _Find_last(_Keyval, _Hashval)._Duplicate;
+            if (_Target) {
+                _Erase_bucket(_Target, _Hashval & _Mask);
+                _List._Unchecked_erase(_Target);
+                return 1;
+            }
+
+            return 0;
+        }
+    }
+
+public:
+    template <class _Iter = iterator, _STD enable_if_t<!_STD is_same_v<_Iter, const_iterator>, int> = 0>
+    iterator erase(iterator _Plist) noexcept(_STD _Nothrow_hash<_Traits, key_type>) /* strengthened */ {
+        return _List._Make_iter(_Unchecked_erase(_Plist._Ptr));
+    }
+
+    iterator erase(const_iterator _Plist) noexcept(_STD _Nothrow_hash<_Traits, key_type>) /* strengthened */ {
+        return _List._Make_iter(_Unchecked_erase(_Plist._Ptr));
+    }
+
+    iterator erase(const_iterator _First, const_iterator _Last) noexcept(
+        _STD _Nothrow_hash<_Traits, key_type>) /* strengthened */ {
+        return _List._Make_iter(_Unchecked_erase(_First._Ptr, _Last._Ptr));
+    }
+
+    size_type erase(const key_type& _Keyval) noexcept(noexcept(_Erase(_Keyval))) /* strengthened */ {
+        return _Erase(_Keyval);
+    }
+
+#if _HAS_CXX23
+    template <class _Kx, class _Mytraits = _Traits,
+        _STD enable_if_t<_Mytraits::template _Supports_transparency<_Hash, _Kx>, int> = 0>
+    size_type erase(_Kx&& _Keyval) noexcept(noexcept(_Erase(_Keyval))) /* strengthened */ {
+        return _Erase(_Keyval);
+    }
+#endif // _HAS_CXX23
+
+    void clear() noexcept {
+        // TRANSITION, ABI:
+        // LWG-2550 requires implementations to make clear() O(size()), independent of bucket_count().
+        // Unfortunately our current data structure / ABI does not allow achieving this in the general case because:
+        //   (1) Finding the bucket that goes with an element requires running the hash function
+        //   (2) The hash function operator() may throw exceptions, and
+        //   (3) clear() is a noexcept function.
+        // We do comply with LWG-2550 if the hash function is noexcept, or if the container was empty.
+        const auto _Oldsize = _List_Mypair()._Myval2._Mysize;
+        if (_Oldsize == 0) {
+            return;
+        }
+
+        if constexpr (_STD _Nothrow_hash<_Traits, key_type>) {
+            // In testing, hash<size_t>{}(size_t{}) takes about 14 times as much time as assigning a pointer, or
+            // ~7-8 times as much as clearing a bucket. Therefore, if we would need to assign over more than 8 times
+            // as many buckets as elements, remove element-by-element.
+            if (bucket_count() / 8 > _Oldsize) {
+                const auto _Head = _List_Mypair()._Myval2._Myhead;
+                _Unchecked_erase(_Head->_Next, _Head);
+                return;
+            }
+        }
+
+        // Bulk destroy items and reset buckets
+        _List.clear();
+        _STD fill(_Vec._Mypair._Myval2._Myfirst, _Vec._Mypair._Myval2._Mylast, _Unchecked_end());
+    }
+
+private:
+    template <class _Keyty>
+    _NODISCARD _Nodeptr _Find_first(const _Keyty& _Keyval, const size_t _Hashval) const {
+        // find node pointer to first node matching _Keyval (with hash _Hashval) if it exists; otherwise, end
+        const size_type _Bucket = _Hashval & _Mask;
+        _Nodeptr _Where         = _Vec._Mypair._Myval2._Myfirst[_Bucket << 1]._Ptr;
+        const _Nodeptr _End     = _List_Mypair()._Myval2._Myhead;
+        if (_Where == _End) {
+            return _End;
+        }
+
+        const _Nodeptr _Bucket_hi = _Vec._Mypair._Myval2._Myfirst[(_Bucket << 1) + 1]._Ptr;
+        for (;;) {
+            if (!_Traitsobj(_Traits::_Kfn(_Where->_Myval), _Keyval)) {
+                if constexpr (!_Traits::_Standard) {
+                    if (_Traitsobj(_Keyval, _Traits::_Kfn(_Where->_Myval))) {
+                        return _End;
+                    }
+                }
+
+                return _Where;
+            }
+
+            if (_Where == _Bucket_hi) {
+                return _End;
+            }
+
+            _Where = _Where->_Next;
+        }
+    }
+
+    template <class _Keyty>
+    _Nodeptr _Find(const _Keyty& _Keyval, const size_t _Hashval) const {
+        if constexpr (_Traits::_Multi) {
+            return _Find_first(_Keyval, _Hashval);
+        } else {
+            // use _Find_last for unique containers to avoid increase in code size of instantiating _Find_first
+            auto _Target = _Find_last(_Keyval, _Hashval)._Duplicate;
+            if (_Target) {
+                return _Target;
+            }
+
+            return _List_Mypair()._Myval2._Myhead;
+        }
+    }
+
+public:
+    template <class _Keyty = void>
+    _NODISCARD iterator find(typename _Traits::template _Deduce_key<_Keyty> _Keyval) {
+        return _List._Make_iter(_Find(_Keyval, _Traitsobj(_Keyval)));
+    }
+
+    template <class _Keyty = void>
+    _NODISCARD const_iterator find(typename _Traits::template _Deduce_key<_Keyty> _Keyval) const {
+        return _List._Make_const_iter(_Find(_Keyval, _Traitsobj(_Keyval)));
+    }
+
+#if _HAS_CXX20
+    template <class _Keyty = void>
+    _NODISCARD bool contains(_Traits::template _Deduce_key<_Keyty> _Keyval) const {
+        return static_cast<bool>(_Find_last(_Keyval, _Traitsobj(_Keyval))._Duplicate);
+    }
+#endif // _HAS_CXX20
+
+    template <class _Keyty = void>
+    _NODISCARD size_type count(typename _Traits::template _Deduce_key<_Keyty> _Keyval) const {
+        const size_t _Hashval = _Traitsobj(_Keyval);
+        if constexpr (_Multi) {
+            return _Equal_range(_Keyval, _Hashval)._Distance;
+        } else {
+            return static_cast<bool>(_Find_last(_Keyval, _Hashval)._Duplicate);
+        }
+    }
+
+    _DEPRECATE_STDEXT_HASH_LOWER_BOUND _NODISCARD iterator lower_bound(const key_type& _Keyval) {
+        return _List._Make_iter(_Find(_Keyval, _Traitsobj(_Keyval)));
+    }
+
+    _DEPRECATE_STDEXT_HASH_LOWER_BOUND _NODISCARD const_iterator lower_bound(const key_type& _Keyval) const {
+        return _List._Make_const_iter(_Find(_Keyval, _Traitsobj(_Keyval)));
+    }
+
+    _DEPRECATE_STDEXT_HASH_UPPER_BOUND _NODISCARD iterator upper_bound(const key_type& _Keyval) {
+        auto _Target = _Find_last(_Keyval, _Traitsobj(_Keyval))._Duplicate;
+        if (_Target) {
+            _Target = _Target->_Next;
+        } else {
+            _Target = _List_Mypair()._Myval2._Myhead;
+        }
+
+        return _List._Make_iter(_Target);
+    }
+
+    _DEPRECATE_STDEXT_HASH_UPPER_BOUND _NODISCARD const_iterator upper_bound(const key_type& _Keyval) const {
+        auto _Target = _Find_last(_Keyval, _Traitsobj(_Keyval))._Duplicate;
+        if (_Target) {
+            _Target = _Target->_Next;
+        } else {
+            _Target = _List_Mypair()._Myval2._Myhead;
+        }
+
+        return _List._Make_const_iter(_Target);
+    }
+
+private:
+    struct _Equal_range_result {
+        _Unchecked_const_iterator _First;
+        _Unchecked_const_iterator _Last;
+        size_type _Distance;
+    };
+
+    template <class _Keyty>
+    _NODISCARD _Equal_range_result _Equal_range(const _Keyty& _Keyval, const size_t _Hashval) const
+        noexcept(_STD _Nothrow_compare<_Traits, key_type, _Keyty>&& _STD _Nothrow_compare<_Traits, _Keyty, key_type>) {
+        const size_type _Bucket              = _Hashval & _Mask;
+        _Unchecked_const_iterator _Where     = _Vec._Mypair._Myval2._Myfirst[_Bucket << 1];
+        const _Unchecked_const_iterator _End = _Unchecked_end();
+        if (_Where == _End) {
+            return {_End, _End, 0};
+        }
+
+        const _Unchecked_const_iterator _Bucket_hi = _Vec._Mypair._Myval2._Myfirst[(_Bucket << 1) + 1];
+        for (; _Traitsobj(_Traits::_Kfn(*_Where), _Keyval); ++_Where) {
+            if (_Where == _Bucket_hi) {
+                return {_End, _End, 0};
+            }
+        }
+
+        if constexpr (!_Traits::_Standard) {
+            if (_Traitsobj(_Keyval, _Traits::_Kfn(*_Where))) {
+                return {_End, _End, 0};
+            }
+        }
+
+        const _Unchecked_const_iterator _First = _Where;
+        if constexpr (_Multi) {
+            size_type _Distance = 0;
+            for (;;) {
+                ++_Distance;
+
+                const bool _At_bucket_end = _Where == _Bucket_hi;
+                ++_Where;
+                if (_At_bucket_end) {
+                    break;
+                }
+
+                if (_Traitsobj(_Keyval, _Traits::_Kfn(*_Where))) {
+                    break;
+                }
+            }
+
+            return {_First, _Where, _Distance};
+        } else {
+            ++_Where; // found the unique element
+            return {_First, _Where, 1};
+        }
+    }
+
+public:
+    template <class _Keyty = void>
+    _NODISCARD _STD pair<iterator, iterator> equal_range(typename _Traits::template _Deduce_key<_Keyty> _Keyval) {
+        const auto _Result = _Equal_range(_Keyval, _Traitsobj(_Keyval));
+        return {_List._Make_iter(_Result._First._Ptr), _List._Make_iter(_Result._Last._Ptr)};
+    }
+
+    template <class _Keyty = void>
+    _NODISCARD _STD pair<const_iterator, const_iterator> equal_range(
+        typename _Traits::template _Deduce_key<_Keyty> _Keyval) const {
+        const auto _Result = _Equal_range(_Keyval, _Traitsobj(_Keyval));
+        return {_List._Make_const_iter(_Result._First._Ptr), _List._Make_const_iter(_Result._Last._Ptr)};
+    }
+
+    void swap(_Hash& _Right) noexcept(noexcept(_Traitsobj.swap(_Right._Traitsobj))) /* strengthened */ {
+        if (this != _STD addressof(_Right)) {
+            _Traitsobj.swap(_Right._Traitsobj);
+            _Pocs(_List_Getal(), _Right._List_Getal());
+            _Pocs(_Vec._Mypair._Get_first(), _Right._Vec._Mypair._Get_first());
+            _Swap_val(_Right);
+        }
+    }
+
+#if _HAS_CXX17
+    using node_type = typename _Traits::node_type;
+
+    node_type extract(const const_iterator _Where) {
+#if _ITERATOR_DEBUG_LEVEL == 2
+        const auto _List_data = _STD addressof(_List_Mypair()._Myval2);
+        _STL_VERIFY(_Where._Getcont() == _List_data, "extract mismatched container");
+        _STL_VERIFY(_Where._Ptr != _List_data->_Myhead, "cannot extract end()");
+#endif // _ITERATOR_DEBUG_LEVEL == 2
+
+        return node_type::_Make(_Extract(_Where._Unwrapped()), _List_Getal());
+    }
+
+    node_type extract(const key_type& _Keyval) {
+        const auto _Ptr = _Extract(_Keyval);
+        if (!_Ptr) {
+            return node_type{};
+        }
+
+        return node_type::_Make(_Ptr, _List_Getal());
+    }
+
+#if _HAS_CXX23
+    template <class _Kx, class _Mytraits = _Traits,
+        _STD enable_if_t<_Mytraits::template _Supports_transparency<_Hash, _Kx>, int> = 0>
+    node_type extract(_Kx&& _Keyval) {
+        const auto _Ptr = _Extract(_Keyval);
+        if (!_Ptr) {
+            return node_type{};
+        }
+
+        return node_type::_Make(_Ptr, _List_Getal());
+    }
+#endif // _HAS_CXX23
+
+    iterator insert(const_iterator _Hint, node_type&& _Handle) {
+        if (_Handle.empty()) {
+            return end();
+        }
+
+#if _ITERATOR_DEBUG_LEVEL == 2
+        _STL_VERIFY(_List.get_allocator() == _Handle._Getal(), "node handle allocator incompatible for insert");
+#endif // _ITERATOR_DEBUG_LEVEL == 2
+
+        const auto& _Keyval   = _Traits::_Kfn(_Handle._Getptr()->_Myval);
+        const size_t _Hashval = _Traitsobj(_Keyval);
+        auto _Target          = _Find_hint(_Hint._Ptr, _Keyval, _Hashval);
+        if constexpr (!_Traits::_Multi) {
+            if (_Target._Duplicate) {
+                return _List._Make_iter(_Target._Duplicate);
+            }
+        }
+
+        _Check_max_size();
+        if (_Check_rehash_required_1()) {
+            _Rehash_for_1();
+            _Target = _Find_hint(_Hint._Ptr, _Keyval, _Hashval);
+        }
+
+        const auto _Released = _Handle._Release();
+        _Destroy_in_place(_Released->_Next); // TRANSITION, ABI
+        _Destroy_in_place(_Released->_Prev);
+        return _List._Make_iter(_Insert_new_node_before(_Hashval, _Target._Insert_before, _Released));
+    }
+
+    template <class>
+    friend class _Hash;
+
+    template <class _Other_traits>
+    void merge(_Hash<_Other_traits>& _That) { // transfer all nodes from _That into *this
+        static_assert(_STD is_same_v<_Nodeptr, typename _Hash<_Other_traits>::_Nodeptr>,
+            "merge() requires an argument with a compatible node type.");
+
+        static_assert(_STD is_same_v<allocator_type, typename _Hash<_Other_traits>::allocator_type>,
+            "merge() requires an argument with the same allocator type.");
+
+        if constexpr (_STD is_same_v<_Hash, _Hash<_Other_traits>>) {
+            if (this == _STD addressof(_That)) {
+                return;
+            }
+        }
+
+#if _ITERATOR_DEBUG_LEVEL == 2
+        if constexpr (!_Alnode_traits::is_always_equal::value) {
+            _STL_VERIFY(_List_Getal() == _That._List_Getal(), "allocator incompatible for merge");
+        }
+#endif // _ITERATOR_DEBUG_LEVEL == 2
+
+        auto _First      = _That._Unchecked_begin();
+        const auto _Last = _That._Unchecked_end();
+        while (_First != _Last) {
+            const auto _Candidate = _First._Ptr;
+            ++_First;
+            const auto& _Keyval   = _Traits::_Kfn(_Candidate->_Myval);
+            const size_t _Hashval = _Traitsobj(_Keyval);
+            auto _Target          = _Find_last(_Keyval, _Hashval);
+            if constexpr (!_Traits::_Multi) {
+                if (_Target._Duplicate) {
+                    continue;
+                }
+            }
+
+            _Check_max_size();
+            if (_Check_rehash_required_1()) {
+                _Rehash_for_1();
+                _Target = _Find_last(_Keyval, _Hashval);
+            }
+
+            // nothrow hereafter this iteration
+            const auto _Source_bucket = _Hashval & _That._Mask;
+            _That._Erase_bucket(_Candidate, _Source_bucket);
+            _Candidate->_Prev->_Next = _Candidate->_Next;
+            _Candidate->_Next->_Prev = _Candidate->_Prev;
+            --_That._List_Mypair()._Myval2._Mysize;
+            _Destroy_in_place(_Candidate->_Next); // TRANSITION, ABI
+            _Destroy_in_place(_Candidate->_Prev);
+#if _ITERATOR_DEBUG_LEVEL == 2
+            _List_Mypair()._Myval2._Adopt_unique(_That._List_Mypair()._Myval2, _Candidate);
+#endif // _ITERATOR_DEBUG_LEVEL == 2
+            (void) _Insert_new_node_before(_Hashval, _Target._Insert_before, _Candidate);
+        }
+    }
+
+    template <class _Other_traits>
+    void merge(_Hash<_Other_traits>&& _That) { // transfer all nodes from _That into *this
+        static_assert(_STD is_same_v<_Nodeptr, typename _Hash<_Other_traits>::_Nodeptr>,
+            "merge() requires an argument with a compatible node type.");
+
+        static_assert(_STD is_same_v<allocator_type, typename _Hash<_Other_traits>::allocator_type>,
+            "merge() requires an argument with the same allocator type.");
+
+        merge(_That);
+    }
+
+protected:
+    _Nodeptr _Extract(const _Unchecked_const_iterator _Where) {
+        const size_type _Bucket = bucket(_Traits::_Kfn(*_Where));
+        _Erase_bucket(_Where._Ptr, _Bucket);
+        return _List_Mypair()._Myval2._Unlinknode(_Where._Ptr);
+    }
+
+    template <class _Kx>
+    _Nodeptr _Extract(const _Kx& _Keyval) {
+        const size_t _Hashval = _Traitsobj(_Keyval);
+        _Nodeptr _Target;
+        if constexpr (_Traits::_Multi) {
+            _Target = _Find_first(_Keyval, _Hashval);
+            if (_Target == _List_Mypair()._Myval2._Myhead) {
+                return _Nodeptr{};
+            }
+        } else {
+            _Target = _Find_last(_Keyval, _Hashval)._Duplicate;
+            if (_Target == nullptr) {
+                return _Nodeptr{};
+            }
+        }
+
+        _Erase_bucket(_Target, _Hashval & _Mask);
+        return _List_Mypair()._Myval2._Unlinknode(_Target);
+    }
+
+public:
+    _STD conditional_t<_Traits::_Multi, iterator, _STD _Insert_return_type<iterator, node_type>> insert(node_type&& _Handle) {
+        // insert the node (if any) held in _Handle
+        if (_Handle.empty()) {
+            if constexpr (_Traits::_Multi) {
+                return end();
+            } else {
+                return {end(), false, _STD move(_Handle)};
+            }
+        }
+
+#if _ITERATOR_DEBUG_LEVEL == 2
+        _STL_VERIFY(_List.get_allocator() == _Handle._Getal(), "node handle allocator incompatible for insert");
+#endif // _ITERATOR_DEBUG_LEVEL == 2
+
+        const auto& _Keyval   = _Traits::_Kfn(_Handle._Getptr()->_Myval);
+        const size_t _Hashval = _Traitsobj(_Keyval);
+        auto _Target          = _Find_last(_Keyval, _Hashval);
+        if constexpr (!_Traits::_Multi) {
+            if (_Target._Duplicate) {
+                return {_List._Make_iter(_Target._Duplicate), false, _STD move(_Handle)};
+            }
+        }
+
+        _Check_max_size();
+        if (_Check_rehash_required_1()) {
+            _Rehash_for_1();
+            _Target = _Find_last(_Keyval, _Hashval);
+        }
+
+        const auto _Released = _Handle._Release();
+        _Destroy_in_place(_Released->_Next); // TRANSITION, ABI
+        _Destroy_in_place(_Released->_Prev);
+        const auto _Newnode = _Insert_new_node_before(_Hashval, _Target._Insert_before, _Released);
+        if constexpr (_Traits::_Multi) {
+            return _List._Make_iter(_Newnode);
+        } else {
+            return {_List._Make_iter(_Newnode), true, node_type{}};
+        }
+    }
+#endif // _HAS_CXX17
+
+protected:
+    template <class _Keyty>
+    _NODISCARD _STD _Hash_find_last_result<_Nodeptr> _Find_last(const _Keyty& _Keyval, const size_t _Hashval) const {
+        // find the insertion point for _Keyval and whether an element identical to _Keyval is already in the container
+        const size_type _Bucket = _Hashval & _Mask;
+        _Nodeptr _Where         = _Vec._Mypair._Myval2._Myfirst[(_Bucket << 1) + 1]._Ptr;
+        const _Nodeptr _End     = _List_Mypair()._Myval2._Myhead;
+        if (_Where == _End) {
+            return {_End, _Nodeptr{}};
+        }
+
+        const _Nodeptr _Bucket_lo = _Vec._Mypair._Myval2._Myfirst[_Bucket << 1]._Ptr;
+        for (;;) {
+            // Search backwards to maintain sorted [_Bucket_lo, _Bucket_hi] when !_Standard
+            if (!_Traitsobj(_Keyval, _Traits::_Kfn(_Where->_Myval))) {
+                if constexpr (!_Traits::_Standard) {
+                    if (_Traitsobj(_Traits::_Kfn(_Where->_Myval), _Keyval)) {
+                        return {_Where->_Next, _Nodeptr{}};
+                    }
+                }
+
+                return {_Where->_Next, _Where};
+            }
+
+            if (_Where == _Bucket_lo) {
+                return {_Where, _Nodeptr{}};
+            }
+
+            _Where = _Where->_Prev;
+        }
+    }
+
+    template <class _Keyty>
+    _NODISCARD _STD _Hash_find_last_result<_Nodeptr> _Find_hint(
+        const _Nodeptr _Hint, const _Keyty& _Keyval, const size_t _Hashval) const {
+        // if _Hint points to an element equivalent to _Keyval, returns _Hint; otherwise,
+        // returns _Find_last(_Keyval, _Hashval)
+        if (_Hint != _List_Mypair()._Myval2._Myhead && !_Traitsobj(_Traits::_Kfn(_Hint->_Myval), _Keyval)) {
+            if constexpr (!_Traits::_Standard) {
+                if (_Traitsobj(_Keyval, _Traits::_Kfn(_Hint->_Myval))) {
+                    return _Find_last(_Keyval, _Hashval);
+                }
+            }
+
+            return {_Hint->_Next, _Hint};
+        }
+
+        return _Find_last(_Keyval, _Hashval);
+    }
+
+    _Nodeptr _Insert_new_node_before(
+        const size_t _Hashval, const _Nodeptr _Insert_before, const _Nodeptr _Newnode) noexcept {
+        const _Nodeptr _Insert_after = _Insert_before->_Prev;
+        ++_List_Mypair()._Myval2._Mysize;
+        _Construct_in_place(_Newnode->_Next, _Insert_before);
+        _Construct_in_place(_Newnode->_Prev, _Insert_after);
+        _Insert_after->_Next  = _Newnode;
+        _Insert_before->_Prev = _Newnode;
+
+        const auto _Head                = _List_Mypair()._Myval2._Myhead;
+        const auto _Bucket_array        = _Vec._Mypair._Myval2._Myfirst;
+        const size_type _Bucket         = _Hashval & _Mask;
+        _Unchecked_iterator& _Bucket_lo = _Bucket_array[_Bucket << 1];
+        _Unchecked_iterator& _Bucket_hi = _Bucket_array[(_Bucket << 1) + 1];
+        if (_Bucket_lo._Ptr == _Head) {
+            // bucket is empty, set both
+            _Bucket_lo._Ptr = _Newnode;
+            _Bucket_hi._Ptr = _Newnode;
+        } else if (_Bucket_lo._Ptr == _Insert_before) {
+            // new node is the lowest element in the bucket
+            _Bucket_lo._Ptr = _Newnode;
+        } else if (_Bucket_hi._Ptr == _Insert_after) {
+            // new node is the highest element in the bucket
+            _Bucket_hi._Ptr = _Newnode;
+        }
+
+#ifdef _ENABLE_STL_INTERNAL_CHECK
+        _Stl_internal_check_container_invariants();
+#endif // _ENABLE_STL_INTERNAL_CHECK
+        return _Newnode;
+    }
+
+    void _Check_max_size() const {
+        const size_type _Oldsize = _List_Mypair()._Myval2._Mysize;
+        if (_Oldsize == _List.max_size()) {
+            _STD _Xlength_error("unordered_map/set too long");
+        }
+    }
+
+    bool _Check_rehash_required_1() const noexcept {
+        const size_type _Oldsize = _List_Mypair()._Myval2._Mysize;
+        const auto _Newsize      = _Oldsize + 1;
+        return max_load_factor() < static_cast<float>(_Newsize) / static_cast<float>(bucket_count());
+    }
+
+    void _Rehash_for_1() {
+        const auto _Oldsize = _List_Mypair()._Myval2._Mysize;
+        const auto _Newsize = _Oldsize + 1;
+        _Forced_rehash(_Desired_grow_bucket_count(_Newsize));
+    }
+
+    void _Erase_bucket(_Nodeptr _Plist, size_type _Bucket) noexcept {
+        // remove the node _Plist from its bucket
+        _Nodeptr& _Bucket_lo = _Vec._Mypair._Myval2._Myfirst[_Bucket << 1]._Ptr;
+        _Nodeptr& _Bucket_hi = _Vec._Mypair._Myval2._Myfirst[(_Bucket << 1) + 1]._Ptr;
+        if (_Bucket_hi == _Plist) {
+            if (_Bucket_lo == _Plist) { // make bucket empty
+                const auto _End = _List_Mypair()._Myval2._Myhead;
+
+                _Bucket_lo = _End;
+                _Bucket_hi = _End;
+            } else {
+                _Bucket_hi = _Plist->_Prev; // move end back one element
+            }
+        } else if (_Bucket_lo == _Plist) {
+            _Bucket_lo = _Plist->_Next; // move beginning up one element
+        }
+    }
+
+    _NODISCARD size_type _Min_load_factor_buckets(const size_type _For_size) const noexcept {
+        // returns the minimum number of buckets necessary for the elements in _List
+        return static_cast<size_type>(_CSTD ceilf(static_cast<float>(_For_size) / max_load_factor()));
+    }
+
+    _NODISCARD size_type _Desired_grow_bucket_count(const size_type _For_size) const noexcept {
+        const size_type _Old_buckets = bucket_count();
+        const size_type _Req_buckets = (_STD max)(_Min_buckets, _Min_load_factor_buckets(_For_size));
+        if (_Old_buckets >= _Req_buckets) {
+            // we already have enough buckets so there's no need to change the count
+            return _Old_buckets;
+        }
+
+        if (_Old_buckets < 512 && _Old_buckets * 8 >= _Req_buckets) {
+            // if we are changing the bucket count and have less than 512 buckets, use 8x more buckets
+            return _Old_buckets * 8;
+        }
+
+        // power of 2 invariant means this will result in at least 2*_Old_buckets after round up in _Forced_rehash
+        return _Req_buckets;
+    }
+
+    void _Reinsert_with_invalid_vec() { // insert elements in [begin(), end()), distrusting existing _Vec elements
+        _Forced_rehash(_Desired_grow_bucket_count(_List.size()));
+    }
+
+    void _Forced_rehash(size_type _Buckets) {
+        // Force rehash of elements in _List, distrusting existing bucket assignments in _Vec.
+        // Assumes _Buckets is greater than _Min_buckets, and that changing to that many buckets doesn't violate
+        // load_factor() <= max_load_factor().
+
+        // Don't violate power of 2, fits in half the bucket vector invariant:
+        // (we assume because vector must use single allocations; as a result, its max_size fits in a size_t)
+        const unsigned long _Max_storage_buckets_log2 = _STD _Floor_of_log_2(static_cast<size_t>(_Vec.max_size() >> 1));
+        const auto _Max_storage_buckets               = static_cast<size_type>(1) << _Max_storage_buckets_log2;
+        if (_Buckets > _Max_storage_buckets) {
+            _STD _Xlength_error("invalid hash bucket count");
+        }
+
+        // The above test also means that we won't perform a forbidden full shift when restoring the power of
+        // 2 invariant
+        // this round up to power of 2 in addition to the _Buckets > _Maxidx above means
+        // we'll at least double in size (the next power of 2 above _Maxidx)
+        _Buckets                       = static_cast<size_type>(1) << _STD _Ceiling_of_log_2(static_cast<size_t>(_Buckets));
+        const _Unchecked_iterator _End = _Unchecked_end();
+
+        _Vec._Assign_grow(_Buckets << 1, _End);
+        _Mask   = _Buckets - 1;
+        _Maxidx = _Buckets;
+
+        _Clear_guard _Guard{this};
+
+        _Unchecked_iterator _Inserted = _Unchecked_begin();
+
+        // Remember the next _Inserted value as splices will change _Inserted's position arbitrarily.
+        for (_Unchecked_iterator _Next_inserted = _Inserted; _Inserted != _End; _Inserted = _Next_inserted) {
+            ++_Next_inserted;
+
+            auto& _Inserted_key     = _Traits::_Kfn(*_Inserted);
+            const size_type _Bucket = bucket(_Inserted_key);
+
+            // _Bucket_lo and _Bucket_hi are the *inclusive* range of elements in the bucket, or _Unchecked_end() if
+            // the bucket is empty; if !_Standard then [_Bucket_lo, _Bucket_hi] is a sorted range.
+            _Unchecked_iterator& _Bucket_lo = _Vec._Mypair._Myval2._Myfirst[_Bucket << 1];
+            _Unchecked_iterator& _Bucket_hi = _Vec._Mypair._Myval2._Myfirst[(_Bucket << 1) + 1];
+
+            if (_Bucket_lo == _End) {
+                // The bucket was empty, set it to the inserted element.
+                _Bucket_lo = _Inserted;
+                _Bucket_hi = _Inserted;
+                continue;
+            }
+
+            // Search the bucket for the insertion location and move element if necessary.
+            _Unchecked_const_iterator _Insert_before = _Bucket_hi;
+            if (!_Traitsobj(_Inserted_key, _Traits::_Kfn(*_Insert_before))) {
+                // The inserted element belongs at the end of the bucket; splice it there and set _Bucket_hi to the
+                // new bucket inclusive end.
+                ++_Insert_before;
+                if (_Insert_before != _Inserted) { // avoid splice on element already in position
+                    _MylistImpl::_Scary_val::_Unchecked_splice(_Insert_before._Ptr, _Inserted._Ptr, _Next_inserted._Ptr);
+                }
+
+                _Bucket_hi = _Inserted;
+                continue;
+            }
+
+            // The insertion point isn't *_Bucket_hi, so search [_Bucket_lo, _Bucket_hi) for insertion point; we
+            // go backwards to maintain sortedness when !_Standard.
+            for (;;) {
+                if (_Bucket_lo == _Insert_before) {
+                    // There are no equivalent keys in the bucket, so insert it at the beginning.
+                    // Element can't be already in position here because:
+                    // * (for !_Standard) _Inserted_key < *_Insert_before or
+                    // * (for _Standard) _Inserted_key != *_Insert_before
+                    _MylistImpl::_Scary_val::_Unchecked_splice(_Insert_before._Ptr, _Inserted._Ptr, _Next_inserted._Ptr);
+                    _Bucket_lo = _Inserted;
+                    break;
+                }
+
+                if (!_Traitsobj(_Inserted_key, _Traits::_Kfn(*--_Insert_before))) {
+                    // Found insertion point, move the element here, bucket bounds are already okay.
+                    ++_Insert_before;
+                    // Element can't be already in position here because all elements we're inserting are after all
+                    // the elements already in buckets, and *_Insert_before isn't the highest element in the bucket.
+                    _MylistImpl::_Scary_val::_Unchecked_splice(_Insert_before._Ptr, _Inserted._Ptr, _Next_inserted._Ptr);
+                    break;
+                }
+            }
+        }
+
+        _Guard._Target = nullptr;
+
+#ifdef _ENABLE_STL_INTERNAL_CHECK
+        _Stl_internal_check_container_invariants();
+#endif // _ENABLE_STL_INTERNAL_CHECK
+    }
+
+    float& _Max_bucket_size() noexcept {
+        return _Traitsobj._Get_max_bucket_size();
+    }
+
+    const float& _Max_bucket_size() const noexcept {
+        return _Traitsobj._Get_max_bucket_size();
+    }
+
+    _Alnode& _Getal() noexcept {
+        return _List_Getal();
+    }
+
+    const _Alnode& _Getal() const noexcept {
+        return _List_Getal();
+    }
+
+    struct _Multi_equal_check_result {
+        bool _Equal_possible = false;
+        _Unchecked_const_iterator _Subsequent_first{}; // only useful if _Equal_possible
+    };
+
+    _NODISCARD _Multi_equal_check_result _Multi_equal_check_equal_range(
+        const _Hash& _Right, _Unchecked_const_iterator _First1) const {
+        // check that an equal_range of elements starting with *_First1 are a permutation of the corresponding
+        // equal_range of elements in _Right
+        auto& _Keyval = _Traits::_Kfn(*_First1);
+        // find the start of the matching run in the other container
+        const size_t _Hashval   = _Right._Traitsobj(_Keyval);
+        const size_type _Bucket = _Hashval & _Right._Mask;
+        auto _First2            = _Right._Vec._Mypair._Myval2._Myfirst[_Bucket << 1];
+        if (_First2 == _Right._Unchecked_end()) {
+            // no matching bucket, therefore no matching run
+            return {};
+        }
+
+        const auto _Bucket_hi = _Right._Vec._Mypair._Myval2._Myfirst[(_Bucket << 1) + 1];
+        for (; _Right._Traitsobj(_Traits::_Kfn(*_First2), _Keyval); ++_First2) {
+            // find first matching element in _Right
+            if (_First2 == _Bucket_hi) {
+                return {};
+            }
+        }
+
+        _Unchecked_const_iterator _Left_stop_at;
+        if constexpr (_Traits::_Standard) {
+            _Left_stop_at = _Unchecked_end();
+        } else {
+            // check the first elements for equivalence when !_Standard
+            if (_Right._Traitsobj(_Keyval, _Traits::_Kfn(*_First2))) {
+                return {};
+            }
+
+            const size_t _LHashval   = _Traitsobj(_Keyval);
+            const size_type _LBucket = _LHashval & _Mask;
+            const auto _LBucket_hi   = _Vec._Mypair._Myval2._Myfirst[(_LBucket << 1) + 1];
+            _Left_stop_at            = _LBucket_hi;
+            ++_Left_stop_at;
+        }
+
+        // trim matching prefixes
+        while (*_First1 == *_First2) {
+            // the right equal_range ends at the end of the bucket or on the first nonequal element
+            bool _Right_range_end = _First2 == _Bucket_hi;
+            ++_First2;
+            if (!_Right_range_end) {
+                _Right_range_end = _Right._Traitsobj(_Keyval, _Traits::_Kfn(*_First2));
+            }
+
+            // the left equal_range ends at the end of the container or on the first nonequal element
+            ++_First1;
+            const bool _Left_range_end = _First1 == _Left_stop_at || _Traitsobj(_Keyval, _Traits::_Kfn(*_First1));
+
+            if (_Left_range_end && _Right_range_end) {
+                // the equal_ranges were completely equal
+                return {true, _First1};
+            }
+
+            if (_Left_range_end || _Right_range_end) {
+                // one equal_range is a prefix of the other; not equal
+                return {};
+            }
+        }
+
+        // found a mismatched element, find the end of the equal_ranges and dispatch to _Check_match_counts
+        auto _Last1 = _First1;
+        auto _Last2 = _First2;
+        for (;;) {
+            bool _Right_range_end = _Last2 == _Bucket_hi;
+            ++_Last2;
+            if (!_Right_range_end) {
+                _Right_range_end = _Right._Traitsobj(_Keyval, _Traits::_Kfn(*_Last2));
+            }
+
+            ++_Last1;
+            const bool _Left_range_end = _Last1 == _Left_stop_at || _Traitsobj(_Keyval, _Traits::_Kfn(*_Last1));
+
+            if (_Left_range_end && _Right_range_end) {
+                // equal_ranges had the same length, check for permutation
+                return {_STD _Check_match_counts(_First1, _Last1, _First2, _Last2, _STD equal_to<>{}), _Last1};
+            }
+
+            if (_Left_range_end || _Right_range_end) {
+                // different number of elements in the range, not a permutation
+                return {};
+            }
+        }
+    }
+
+    template <bool _Multi2 = _Traits::_Multi, _STD enable_if_t<_Multi2, int> = 0>
+    _NODISCARD bool _Multi_equal(const _Hash& _Right) const {
+        static_assert(_Traits::_Multi, "This function only works with multi containers");
+        _STL_INTERNAL_CHECK(this->size() == _Right.size());
+        const auto _Last1 = _Unchecked_end();
+        auto _First1      = _Unchecked_begin();
+        while (_First1 != _Last1) {
+            const auto _Result = _Multi_equal_check_equal_range(_Right, _First1);
+            if (!_Result._Equal_possible) {
+                return false;
+            }
+
+            _First1 = _Result._Subsequent_first;
+        }
+
+        return true;
+    }
+
+#ifdef _ENABLE_STL_INTERNAL_CHECK
+public:
+    void _Stl_internal_check_container_invariants() const noexcept {
+        const size_type _Vecsize = _Vec.size();
+        _STL_INTERNAL_CHECK(_Vec._Mypair._Myval2._Mylast == _Vec._Mypair._Myval2._Myend);
+        _STL_INTERNAL_CHECK(_Vecsize >= _Min_buckets * 2);
+        _STL_INTERNAL_CHECK(_Maxidx == (_Vecsize >> 1));
+        _STL_INTERNAL_CHECK(_Maxidx - 1 == _Mask);
+        _STL_INTERNAL_CHECK(_Maxidx >= _Min_load_factor_buckets(_List.size()));
+        // asserts that bucket count is a power of 2:
+        _STL_INTERNAL_CHECK((static_cast<size_type>(1) << _STD _Floor_of_log_2(_Vecsize)) == _Vecsize);
+        _STL_INTERNAL_CHECK(load_factor() <= max_load_factor());
+        // In the test that counts number of allocator copies, avoid an extra rebind that would incorrectly count as
+        // a copy; otherwise, allow allocators that support only homogeneous compare.
+#ifdef _USE_HETEROGENEOUS_ALLOCATOR_COMPARE_IN_INTERNAL_CHECK
+        _STL_INTERNAL_CHECK(_List_Getal() == _Vec._Mypair._Get_first());
+#else
+        _STL_INTERNAL_CHECK(static_cast<_Aliter>(_List_Getal()) == _Vec._Mypair._Get_first());
+#endif
+#ifdef _STL_INTERNAL_CHECK_EXHAUSTIVE
+        size_type _Elements = 0;
+        const auto _End     = _Unchecked_end();
+        for (size_type _Bucket = 0; _Bucket < _Maxidx; ++_Bucket) {
+            _Unchecked_const_iterator _Where           = _Vec._Mypair._Myval2._Myfirst[_Bucket << 1];
+            const _Unchecked_const_iterator _Bucket_hi = _Vec._Mypair._Myval2._Myfirst[(_Bucket << 1) + 1];
+            if (_Where != _End) {
+                // check that the bucket is sorted for legacy hash_meow:
+                if constexpr (!_Traits::_Standard) {
+                    if (_Where != _Bucket_hi) {
+                        auto _SFirst = _Where;
+                        auto _SNext  = _Where;
+                        for (;;) {
+                            ++_SNext;
+                            if constexpr (_Traits::_Multi) {
+                                _STL_INTERNAL_CHECK(!_Traitsobj(_Traits::_Kfn(*_SNext), _Traits::_Kfn(*_SFirst)));
+                            } else {
+                                _STL_INTERNAL_CHECK(_Traitsobj(_Traits::_Kfn(*_SFirst), _Traits::_Kfn(*_SNext)));
+                            }
+
+                            if (_SNext == _Bucket_hi) {
+                                break;
+                            }
+
+                            _SFirst = _SNext;
+                        }
+                    }
+                }
+                // check that all the elements in the bucket belong in the bucket:
+                for (;;) {
+                    ++_Elements;
+                    _STL_INTERNAL_CHECK(bucket(_Traits::_Kfn(*_Where)) == _Bucket);
+                    if (_Where == _Bucket_hi) {
+                        break;
+                    }
+
+                    ++_Where;
+                }
+            }
+        }
+
+        _STL_INTERNAL_CHECK(_List.size() == _Elements);
+#endif // _STL_INTERNAL_CHECK_EXHAUSTIVE
+    }
+
+protected:
+#endif // _ENABLE_STL_INTERNAL_CHECK
+
+    _Mylist _List; // list of elements, must initialize before _Vec
+    _STD _Hash_vec<_Aliter> _Vec; // "vector" of list iterators for buckets:
+                             // each bucket is 2 iterators denoting the closed range of elements in the bucket,
+                             // or both iterators set to _Unchecked_end() if the bucket is empty.
+    size_type _Mask; // the key mask
+    size_type _Maxidx; // current maximum key value, must be a power of 2
+    _Traits _Traitsobj; // traits to customize behavior
+};
+
+#if _HAS_CXX17
+// For constraining deduction guides (N4950 [unord.req.general]/243.3)
+template <class _Hasher>
+using _Is_hasher = _STD negation<_STD disjunction<_STD is_integral<_Hasher>, _STD _Is_allocator<_Hasher>>>;
+#endif // _HAS_CXX17
+
+/*_EXPORT_STD*/ /* TRANSITION, VSO-1538698 */ template <class _Traits>
+_NODISCARD bool _Hash_equal(const _Hash<_Traits>& _Left, const _Hash<_Traits>& _Right) {
+    if (_Left.size() != _Right.size()) {
+        return false;
+    }
+
+    if constexpr (_Traits::_Multi) {
+        return _Left._Multi_equal(_Right);
+    } else {
+        for (const auto& _LVal : _Left) {
+            // look for element with equivalent key
+            const auto& _Keyval = _Traits::_Kfn(_LVal);
+            const auto _Next2   = _Right._Find_last(_Keyval, _Right._Traitsobj(_Keyval))._Duplicate;
+            if (!(static_cast<bool>(_Next2) && _Traits::_Nonkfn(_LVal) == _Traits::_Nonkfn(_Next2->_Myval))) {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+_STD_END
+
+#pragma pop_macro("new")
+_STL_RESTORE_CLANG_WARNINGS
+#pragma warning(pop)
+#pragma pack(pop)
+#endif // _STL_COMPILER_PREPROCESSOR
+#endif // _GEODE_XHASH_
diff --git a/loader/include/Geode/c++stl/msvcstl.hpp b/loader/include/Geode/c++stl/msvcstl.hpp
index 88d5a34f..d05fae98 100644
--- a/loader/include/Geode/c++stl/msvcstl.hpp
+++ b/loader/include/Geode/c++stl/msvcstl.hpp
@@ -1,9 +1,11 @@
 #pragma once
 
+#include "msvc/allocator.hpp"
+#include "msvc/umap.hpp"
+#include "msvc/uset.hpp"
+
 #include <map>
 #include <vector>
-#include <unordered_map>
-#include <unordered_set>
 #include <set>
 
 namespace gd {
@@ -14,11 +16,11 @@ namespace gd {
     using map = std::map<K, V>;
 
     template <class K, class V>
-    using unordered_map = std::unordered_map<K, V>;
+    using unordered_map = geode::stl::unordered_map<K, V, std::hash<K>, std::equal_to<K>, geode::stl::allocator<std::pair<const K, V>>>;
 
     template <class K>
     using set = std::set<K>;
 
     template <class K>
-    using unordered_set = std::unordered_set<K>;
+    using unordered_set = geode::stl::unordered_set<K, std::hash<K>, std::equal_to<K>, geode::stl::allocator<K>>;
 }
diff --git a/loader/src/platform/windows/gdstdlib.cpp b/loader/src/platform/windows/gdstdlib.cpp
index ada3675b..c43449ea 100644
--- a/loader/src/platform/windows/gdstdlib.cpp
+++ b/loader/src/platform/windows/gdstdlib.cpp
@@ -1,5 +1,27 @@
+#include "../../c++stl/msvc/allocator.hpp"
 #include "../../c++stl/string-impl.hpp"
 
+static auto constexpr NEW_SYM = "??2@YAPAXI@Z";
+static auto constexpr DELETE_SYM = "??3@YAXPAX@Z";
+
+static void* getFn(const char* sym) {
+    auto msvcr = GetModuleHandleW(L"MSVCR120.dll");
+    if (msvcr != NULL)
+        return reinterpret_cast<void*>(GetProcAddress(msvcr, sym));
+
+    return nullptr;
+}
+
+void* geode::stl::operatorNew(size_t size) {
+    static auto fnPtr = reinterpret_cast<void*(*)(size_t)>(getFn(NEW_SYM));
+    return fnPtr(size);
+}
+
+void geode::stl::operatorDelete(void* ptr) {
+    static auto fnPtr = reinterpret_cast<void(*)(void*)>(getFn(DELETE_SYM));
+    return fnPtr(ptr);
+}
+
 namespace geode::stl {
     void StringImpl::setEmpty() {
         data.m_size = 0;