Skip to content

Commit e00eeaf

Browse files
stinosdpgeorge
authored andcommitted
py: Use __hash__ method if a type defines it
1 parent d8474d3 commit e00eeaf

2 files changed

Lines changed: 17 additions & 8 deletions

File tree

py/obj.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,17 +172,25 @@ mp_int_t mp_obj_hash(mp_obj_t o_in) {
172172
return mp_obj_tuple_hash(o_in);
173173
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_type)) {
174174
return (mp_int_t)o_in;
175+
} else if (MP_OBJ_IS_OBJ(o_in)) {
176+
// if a valid __hash__ method exists, use it
177+
mp_obj_t hash_method[2];
178+
mp_load_method_maybe(o_in, MP_QSTR___hash__, hash_method);
179+
if (hash_method[0] != MP_OBJ_NULL) {
180+
mp_obj_t hash_val = mp_call_method_n_kw(0, 0, hash_method);
181+
if (MP_OBJ_IS_INT(hash_val)) {
182+
return mp_obj_int_get(hash_val);
183+
}
184+
}
185+
}
175186

176-
// TODO hash class and instances
177-
// TODO delegate to __hash__ method if it exists
187+
// TODO hash class and instances - in CPython by default user created classes' __hash__ resolves to their id
178188

189+
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
190+
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "unhashable type"));
179191
} else {
180-
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
181-
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "unhashable type"));
182-
} else {
183-
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
184-
"unhashable type: '%s'", mp_obj_get_type_str(o_in)));
185-
}
192+
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
193+
"unhashable type: '%s'", mp_obj_get_type_str(o_in)));
186194
}
187195
}
188196

py/qstrdefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Q(__locals__)
3939
Q(__main__)
4040
Q(__module__)
4141
Q(__name__)
42+
Q(__hash__)
4243
Q(__next__)
4344
Q(__qualname__)
4445
Q(__path__)

0 commit comments

Comments
 (0)