diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index aefa8e19c1864..cc5f6d1348e41 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -29,6 +29,7 @@ #include <__memory/unique_ptr.h> #include <__new/launder.h> #include <__type_traits/can_extract_key.h> +#include <__type_traits/copy_cvref.h> #include <__type_traits/enable_if.h> #include <__type_traits/invoke.h> #include <__type_traits/is_const.h> @@ -108,9 +109,22 @@ struct __hash_node_base { _LIBCPP_HIDE_FROM_ABI explicit __hash_node_base(__next_pointer __next) _NOEXCEPT : __next_(__next) {} }; +template +struct __get_hash_node_value_type { + using type _LIBCPP_NODEBUG = _Tp; +}; + +template +struct __get_hash_node_value_type<__hash_value_type<_Key, _Tp> > { + using type _LIBCPP_NODEBUG = pair; +}; + +template +using __get_hash_node_value_type_t _LIBCPP_NODEBUG = typename __get_hash_node_value_type<_Tp>::type; + template struct __hash_node : public __hash_node_base< __rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > > { - typedef _Tp __node_value_type; + using __node_value_type _LIBCPP_NODEBUG = __get_hash_node_value_type_t<_Tp>; using _Base _LIBCPP_NODEBUG = __hash_node_base<__rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > >; using __next_pointer _LIBCPP_NODEBUG = typename _Base::__next_pointer; @@ -122,18 +136,20 @@ struct __hash_node : public __hash_node_base< __rebind_pointer_t<_VoidPtr, __has private: union { - _Tp __value_; + __node_value_type __value_; }; public: - _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return __value_; } + _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; } #else private: - _ALIGNAS_TYPE(_Tp) char __buffer_[sizeof(_Tp)]; + _ALIGNAS_TYPE(__node_value_type) char __buffer_[sizeof(__node_value_type)]; public: - _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_)); } + _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { + return *std::__launder(reinterpret_cast<__node_value_type*>(&__buffer_)); + } #endif _LIBCPP_HIDE_FROM_ABI explicit __hash_node(__next_pointer __next, size_t __hash) : _Base(__next), __hash_(__hash) {} @@ -201,8 +217,8 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { return __t; } - _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { - return std::addressof(__n.__get_value()); + _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__container_value_type& __n) { + return std::addressof(__n); } _LIBCPP_HIDE_FROM_ABI static pair __move(__node_value_type& __v) { return __v.__move(); } }; @@ -242,7 +258,7 @@ public: typedef typename __node_base_type::__next_pointer __next_pointer; - typedef _Tp __node_value_type; + using __node_value_type _LIBCPP_NODEBUG = __get_hash_node_value_type_t<_Tp>; typedef __rebind_pointer_t<_VoidPtr, __node_value_type> __node_value_type_pointer; typedef __rebind_pointer_t<_VoidPtr, const __node_value_type> __const_node_value_type_pointer; @@ -667,14 +683,14 @@ int __diagnose_unordered_container_requirements(void*); template class __hash_table { public: - typedef _Tp value_type; + using value_type = __get_hash_node_value_type_t<_Tp>; typedef _Hash hasher; typedef _Equal key_equal; typedef _Alloc allocator_type; private: typedef allocator_traits __alloc_traits; - typedef typename __make_hash_node_types::type _NodeTypes; + typedef typename __make_hash_node_types<_Tp, typename __alloc_traits::void_pointer>::type _NodeTypes; public: typedef typename _NodeTypes::__node_value_type __node_value_type; @@ -845,6 +861,22 @@ public: return __emplace_unique(std::forward<_Pp>(__x)); } + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __insert_unique_from_orphaned_node(value_type&& __value) { + using __key_type = typename _NodeTypes::key_type; + + __node_holder __h = __construct_node(const_cast<__key_type&&>(__value.first), std::move(__value.second)); + __node_insert_unique(__h.get()); + __h.release(); + } + + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __insert_unique_from_orphaned_node(value_type&& __value) { + __node_holder __h = __construct_node(std::move(__value)); + __node_insert_unique(__h.get()); + __h.release(); + } + template _LIBCPP_HIDE_FROM_ABI iterator __insert_multi(_Pp&& __x) { return __emplace_multi(std::forward<_Pp>(__x)); @@ -855,6 +887,22 @@ public: return __emplace_hint_multi(__p, std::forward<_Pp>(__x)); } + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __insert_multi_from_orphaned_node(value_type&& __value) { + using __key_type = typename _NodeTypes::key_type; + + __node_holder __h = __construct_node(const_cast<__key_type&&>(__value.first), std::move(__value.second)); + __node_insert_multi(__h.get()); + __h.release(); + } + + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __insert_multi_from_orphaned_node(value_type&& __value) { + __node_holder __h = __construct_node(std::move(__value)); + __node_insert_multi(__h.get()); + __h.release(); + } + _LIBCPP_HIDE_FROM_ABI pair __insert_unique(const __container_value_type& __x) { return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x); } @@ -1020,6 +1068,21 @@ private: _LIBCPP_HIDE_FROM_ABI void __deallocate_node(__next_pointer __np) _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI __next_pointer __detach() _NOEXCEPT; + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __assign_value(__get_hash_node_value_type_t<_Tp>& __lhs, _From&& __rhs) { + using __key_type = typename _NodeTypes::key_type; + + // This is technically UB, since the object was constructed as `const`. + // Clang doesn't optimize on this currently though. + const_cast<__key_type&>(__lhs.first) = const_cast<__copy_cvref_t<_From, __key_type>&&>(__rhs.first); + __lhs.second = std::forward<_From>(__rhs).second; + } + + template ::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI void __assign_value(_Tp& __lhs, _From&& __rhs) { + __lhs = std::forward<_From>(__rhs); + } + template friend class unordered_map; template @@ -1216,8 +1279,8 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u, #endif // _LIBCPP_HAS_EXCEPTIONS const_iterator __i = __u.begin(); while (__cache != nullptr && __u.size() != 0) { - __cache->__upcast()->__get_value() = std::move(__u.remove(__i++)->__get_value()); - __next_pointer __next = __cache->__next_; + __assign_value(__cache->__upcast()->__get_value(), std::move(__u.remove(__i++)->__get_value())); + __next_pointer __next = __cache->__next_; __node_insert_multi(__cache->__upcast()); __cache = __next; } @@ -1230,11 +1293,8 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u, __deallocate_node(__cache); } const_iterator __i = __u.begin(); - while (__u.size() != 0) { - __node_holder __h = __construct_node(_NodeTypes::__move(__u.remove(__i++)->__get_value())); - __node_insert_multi(__h.get()); - __h.release(); - } + while (__u.size() != 0) + __insert_multi_from_orphaned_node(std::move(__u.remove(__i++)->__get_value())); } } @@ -1262,8 +1322,8 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __ try { #endif // _LIBCPP_HAS_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { - __cache->__upcast()->__get_value() = *__first; - __next_pointer __next = __cache->__next_; + __assign_value(__cache->__upcast()->__get_value(), *__first); + __next_pointer __next = __cache->__next_; __node_insert_unique(__cache->__upcast()); __cache = __next; } @@ -1294,7 +1354,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __f try { #endif // _LIBCPP_HAS_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { - __cache->__upcast()->__get_value() = *__first; + __assign_value(__cache->__upcast()->__get_value(), *__first); __next_pointer __next = __cache->__next_; __node_insert_multi(__cache->__upcast()); __cache = __next; diff --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map index b7f333e5f1178..484f22ce5d72d 100644 --- a/libcxx/include/unordered_map +++ b/libcxx/include/unordered_map @@ -654,9 +654,7 @@ public: _LIBCPP_HIDE_FROM_ABI __unordered_map_hasher(const _Hash& __h) _NOEXCEPT_(is_nothrow_copy_constructible<_Hash>::value) : _Hash(__h) {} _LIBCPP_HIDE_FROM_ABI const _Hash& hash_function() const _NOEXCEPT { return *this; } - _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Cp& __x) const { - return static_cast(*this)(__x.__get_value().first); - } + _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Cp& __x) const { return static_cast(*this)(__x.first); } _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Key& __x) const { return static_cast(*this)(__x); } # if _LIBCPP_STD_VER >= 20 template @@ -680,7 +678,7 @@ public: _LIBCPP_HIDE_FROM_ABI __unordered_map_hasher(const _Hash& __h) _NOEXCEPT_(is_nothrow_copy_constructible<_Hash>::value) : __hash_(__h) {} _LIBCPP_HIDE_FROM_ABI const _Hash& hash_function() const _NOEXCEPT { return __hash_; } - _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Cp& __x) const { return __hash_(__x.__get_value().first); } + _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Cp& __x) const { return __hash_(__x.first); } _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Key& __x) const { return __hash_(__x); } # if _LIBCPP_STD_VER >= 20 template @@ -713,10 +711,10 @@ public: : _Pred(__p) {} _LIBCPP_HIDE_FROM_ABI const _Pred& key_eq() const _NOEXCEPT { return *this; } _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _Cp& __y) const { - return static_cast(*this)(__x.__get_value().first, __y.__get_value().first); + return static_cast(*this)(__x.first, __y.first); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _Key& __y) const { - return static_cast(*this)(__x.__get_value().first, __y); + return static_cast(*this)(__x.first, __y); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _Cp& __y) const { return static_cast(*this)(__x, __y.__get_value().first); @@ -724,7 +722,7 @@ public: # if _LIBCPP_STD_VER >= 20 template _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _K2& __y) const { - return static_cast(*this)(__x.__get_value().first, __y); + return static_cast(*this)(__x.first, __y); } template _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _Cp& __y) const { @@ -755,23 +753,17 @@ public: _LIBCPP_HIDE_FROM_ABI __unordered_map_equal(const _Pred& __p) _NOEXCEPT_(is_nothrow_copy_constructible<_Pred>::value) : __pred_(__p) {} _LIBCPP_HIDE_FROM_ABI const _Pred& key_eq() const _NOEXCEPT { return __pred_; } - _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _Cp& __y) const { - return __pred_(__x.__get_value().first, __y.__get_value().first); - } - _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _Key& __y) const { - return __pred_(__x.__get_value().first, __y); - } - _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _Cp& __y) const { - return __pred_(__x, __y.__get_value().first); - } + _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _Cp& __y) const { return __pred_(__x.first, __y.first); } + _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _Key& __y) const { return __pred_(__x.first, __y); } + _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _Cp& __y) const { return __pred_(__x, __y.first); } # if _LIBCPP_STD_VER >= 20 template _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _K2& __y) const { - return __pred_(__x.__get_value().first, __y); + return __pred_(__x.first, __y); } template _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _Cp& __y) const { - return __pred_(__x, __y.__get_value().first); + return __pred_(__x, __y.first); } template _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _K2& __y) const { @@ -833,96 +825,16 @@ public: _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { if (__second_constructed) - __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().__get_value().second)); + __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().second)); if (__first_constructed) - __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().__get_value().first)); + __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().first)); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } }; -# ifndef _LIBCPP_CXX03_LANG template -struct _LIBCPP_STANDALONE_DEBUG __hash_value_type { - typedef _Key key_type; - typedef _Tp mapped_type; - typedef pair value_type; - typedef pair __nc_ref_pair_type; - typedef pair __nc_rref_pair_type; - -private: - value_type __cc_; - -public: - _LIBCPP_HIDE_FROM_ABI value_type& __get_value() { -# if _LIBCPP_STD_VER >= 17 - return *std::launder(std::addressof(__cc_)); -# else - return __cc_; -# endif - } - - _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const { -# if _LIBCPP_STD_VER >= 17 - return *std::launder(std::addressof(__cc_)); -# else - return __cc_; -# endif - } - - _LIBCPP_HIDE_FROM_ABI __nc_ref_pair_type __ref() { - value_type& __v = __get_value(); - return __nc_ref_pair_type(const_cast(__v.first), __v.second); - } - - _LIBCPP_HIDE_FROM_ABI __nc_rref_pair_type __move() { - value_type& __v = __get_value(); - return __nc_rref_pair_type(std::move(const_cast(__v.first)), std::move(__v.second)); - } - - _LIBCPP_HIDE_FROM_ABI __hash_value_type& operator=(const __hash_value_type& __v) { - __ref() = __v.__get_value(); - return *this; - } - - _LIBCPP_HIDE_FROM_ABI __hash_value_type& operator=(__hash_value_type&& __v) { - __ref() = __v.__move(); - return *this; - } - - template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI __hash_value_type& operator=(_ValueTp&& __v) { - __ref() = std::forward<_ValueTp>(__v); - return *this; - } - - __hash_value_type(const __hash_value_type& __v) = delete; - __hash_value_type(__hash_value_type&& __v) = delete; - template - explicit __hash_value_type(_Args&&... __args) = delete; - - ~__hash_value_type() = delete; -}; - -# else - -template -struct __hash_value_type { - typedef _Key key_type; - typedef _Tp mapped_type; - typedef pair value_type; - -private: - value_type __cc_; - -public: - _LIBCPP_HIDE_FROM_ABI value_type& __get_value() { return __cc_; } - _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const { return __cc_; } - - ~__hash_value_type() = delete; -}; - -# endif +struct __hash_value_type; template class __hash_map_iterator { @@ -941,8 +853,8 @@ public: _LIBCPP_HIDE_FROM_ABI __hash_map_iterator(_HashIterator __i) _NOEXCEPT : __i_(__i) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __i_->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__i_->__get_value()); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { return *__i_; } + _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(*__i_); } _LIBCPP_HIDE_FROM_ABI __hash_map_iterator& operator++() { ++__i_; @@ -995,8 +907,8 @@ public: __hash_map_const_iterator(__hash_map_iterator __i) _NOEXCEPT : __i_(__i.__i_) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __i_->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__i_->__get_value()); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { return *__i_; } + _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(*__i_); } _LIBCPP_HIDE_FROM_ABI __hash_map_const_iterator& operator++() { ++__i_; @@ -1053,8 +965,8 @@ public: private: typedef __hash_value_type __value_type; - typedef __unordered_map_hasher __hasher; - typedef __unordered_map_equal __key_equal; + typedef __unordered_map_hasher __hasher; + typedef __unordered_map_equal __key_equal; typedef __rebind_alloc, __value_type> __allocator_type; typedef __hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table; @@ -1073,9 +985,6 @@ private: static_assert(__check_valid_allocator::value, ""); - static_assert(is_same::value, ""); - static_assert(is_same::value, ""); - public: typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; @@ -1680,9 +1589,8 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map(unordered_map&& __ : __table_(std::move(__u.__table_), typename __table::allocator_type(__a)) { if (__a != __u.get_allocator()) { iterator __i = __u.begin(); - while (__u.size() != 0) { - __table_.__emplace_unique(__u.__table_.remove((__i++).__i_)->__get_value().__move()); - } + while (__u.size() != 0) + __table_.__insert_unique_from_orphaned_node(std::move(__u.__table_.remove((__i++).__i_)->__get_value())); } } @@ -1741,8 +1649,7 @@ template _Tp& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type& __k) { return __table_ .__emplace_unique_key_args(__k, piecewise_construct, std::forward_as_tuple(__k), std::forward_as_tuple()) - .first->__get_value() - .second; + .first->second; } template @@ -1750,8 +1657,7 @@ _Tp& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](key_type&& __k) return __table_ .__emplace_unique_key_args( __k, piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple()) - .first->__get_value() - .second; + .first->second; } # else // _LIBCPP_CXX03_LANG @@ -1760,9 +1666,9 @@ typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node_with_key(const key_type& __k) { __node_allocator& __na = __table_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); - __node_traits::construct(__na, std::addressof(__h->__get_value().__get_value().first), __k); + __node_traits::construct(__na, std::addressof(__h->__get_value().first), __k); __h.get_deleter().__first_constructed = true; - __node_traits::construct(__na, std::addressof(__h->__get_value().__get_value().second)); + __node_traits::construct(__na, std::addressof(__h->__get_value().second)); __h.get_deleter().__second_constructed = true; return __h; } @@ -1869,8 +1775,8 @@ public: private: typedef __hash_value_type __value_type; - typedef __unordered_map_hasher __hasher; - typedef __unordered_map_equal __key_equal; + typedef __unordered_map_hasher __hasher; + typedef __unordered_map_equal __key_equal; typedef __rebind_alloc, __value_type> __allocator_type; typedef __hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table; @@ -2439,9 +2345,8 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( : __table_(std::move(__u.__table_), typename __table::allocator_type(__a)) { if (__a != __u.get_allocator()) { iterator __i = __u.begin(); - while (__u.size() != 0) { - __table_.__insert_multi(__u.__table_.remove((__i++).__i_)->__get_value().__move()); - } + while (__u.size() != 0) + __table_.__insert_multi_from_orphaned_node(std::move(__u.__table_.remove((__i++).__i_)->__get_value())); } } diff --git a/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/assign_copy.pass.cpp b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/assign_copy.pass.cpp index 25851e941a7d1..e606e538efcbe 100644 --- a/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/assign_copy.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/assign_copy.pass.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "test_macros.h" #include "../../../test_compare.h" @@ -109,6 +110,19 @@ int main(int, char**) { assert(c.max_load_factor() == 1); } #endif + { // Test with std::pair, since we have some special handling for pairs inside __hash_table + struct pair_hash { + size_t operator()(std::pair val) const TEST_NOEXCEPT { return val.first | val.second; } + }; + + std::pair arr[] = { + std::make_pair(1, 2), std::make_pair(2, 3), std::make_pair(3, 4), std::make_pair(4, 5)}; + std::unordered_set, pair_hash> a(arr, arr + 4); + std::unordered_set, pair_hash> b; + + b = a; + assert(a == b); + } return 0; } diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py index 90bc54d987ee8..1c8ef6d7feb97 100644 --- a/libcxx/utils/gdb/libcxx/printers.py +++ b/libcxx/utils/gdb/libcxx/printers.py @@ -65,16 +65,6 @@ def _remove_generics(typename): return match.group(1) -def _cc_field(node): - """Previous versions of libcxx had inconsistent field naming naming. Handle - both types. - """ - try: - return node["__value_"]["__cc_"] - except: - return node["__value_"]["__cc"] - - def _data_field(node): """Previous versions of libcxx had inconsistent field naming naming. Handle both types. @@ -829,7 +819,7 @@ class StdUnorderedMapPrinter(AbstractUnorderedCollectionPrinter): """Print a std::unordered_(multi)map.""" def _get_key_value(self, node): - key_value = _cc_field(node) + key_value = node["__value_"] return [key_value["first"], key_value["second"]] def display_hint(self): @@ -885,7 +875,7 @@ def __init__(self, val): self._initialize(val, val["__i_"]["__node_"]) def _get_key_value(self): - key_value = _cc_field(self.node) + key_value = self.node["__value_"] return [key_value["first"], key_value["second"]] def display_hint(self):