Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Lib/test/test_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -1868,6 +1868,11 @@ def test_merge(self):
self.assertEqual(fd | {}, fd)
self.assertEqual(frozendict() | fd, fd)

# gh-149676: Test hash(frozendict | frozendict)
a = frozendict({"a": 1})
b = frozendict({"b": 2})
self.assertEqual(hash(a | b), hash(frozendict({"a": 1, "b": 2})))

def test_update(self):
# test "a |= b" operator
d = frozendict(x=1)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix frozendict | frozendict hash.
Comment thread
vstinner marked this conversation as resolved.
Outdated
9 changes: 6 additions & 3 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -900,7 +900,7 @@ free_values(PyDictValues *values, bool use_qsbr)
static inline PyObject *
new_dict_impl(PyDictObject *mp, PyDictKeysObject *keys,
PyDictValues *values, Py_ssize_t used,
int free_values_on_failure)
int free_values_on_failure, int frozendict)
{
assert(keys != NULL);
if (mp == NULL) {
Expand All @@ -915,6 +915,9 @@ new_dict_impl(PyDictObject *mp, PyDictKeysObject *keys,
mp->ma_values = values;
mp->ma_used = used;
mp->_ma_watcher_tag = 0;
if (frozendict) {
((PyFrozenDictObject *)mp)->ma_hash = -1;
}
ASSERT_CONSISTENT(mp);
_PyObject_GC_TRACK(mp);
return (PyObject *)mp;
Expand All @@ -931,7 +934,7 @@ new_dict(PyDictKeysObject *keys, PyDictValues *values,
}
assert(mp == NULL || Py_IS_TYPE(mp, &PyDict_Type));

return new_dict_impl(mp, keys, values, used, free_values_on_failure);
return new_dict_impl(mp, keys, values, used, free_values_on_failure, 0);
}

/* Consumes a reference to the keys object */
Expand All @@ -940,7 +943,7 @@ new_frozendict(PyDictKeysObject *keys, PyDictValues *values,
Py_ssize_t used, int free_values_on_failure)
{
PyDictObject *mp = PyObject_GC_New(PyDictObject, &PyFrozenDict_Type);
return new_dict_impl(mp, keys, values, used, free_values_on_failure);
return new_dict_impl(mp, keys, values, used, free_values_on_failure, 1);
}

static PyObject *
Expand Down
Loading