Restore Hash#compare_by_identity mode [Bug #18171]
This commit is contained in:
parent
806e7947fe
commit
d087214658
Notes:
git
2021-10-02 11:43:55 +09:00
@ -7547,6 +7547,7 @@ marshal.$(OBJEXT): $(top_srcdir)/internal/serial.h
|
|||||||
marshal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
|
marshal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
|
||||||
marshal.$(OBJEXT): $(top_srcdir)/internal/string.h
|
marshal.$(OBJEXT): $(top_srcdir)/internal/string.h
|
||||||
marshal.$(OBJEXT): $(top_srcdir)/internal/struct.h
|
marshal.$(OBJEXT): $(top_srcdir)/internal/struct.h
|
||||||
|
marshal.$(OBJEXT): $(top_srcdir)/internal/symbol.h
|
||||||
marshal.$(OBJEXT): $(top_srcdir)/internal/util.h
|
marshal.$(OBJEXT): $(top_srcdir)/internal/util.h
|
||||||
marshal.$(OBJEXT): $(top_srcdir)/internal/vm.h
|
marshal.$(OBJEXT): $(top_srcdir)/internal/vm.h
|
||||||
marshal.$(OBJEXT): $(top_srcdir)/internal/warnings.h
|
marshal.$(OBJEXT): $(top_srcdir)/internal/warnings.h
|
||||||
|
4
hash.c
4
hash.c
@ -1548,8 +1548,6 @@ rb_hash_new(void)
|
|||||||
return hash_alloc(rb_cHash);
|
return hash_alloc(rb_cHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE rb_hash_compare_by_id(VALUE hash);
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
copy_compare_by_id(VALUE hash, VALUE basis)
|
copy_compare_by_id(VALUE hash, VALUE basis)
|
||||||
{
|
{
|
||||||
@ -4380,7 +4378,7 @@ static st_table *rb_init_identtable_with_size(st_index_t size);
|
|||||||
* h # => {"x"=>0, "x"=>1}
|
* h # => {"x"=>0, "x"=>1}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static VALUE
|
VALUE
|
||||||
rb_hash_compare_by_id(VALUE hash)
|
rb_hash_compare_by_id(VALUE hash)
|
||||||
{
|
{
|
||||||
VALUE tmp;
|
VALUE tmp;
|
||||||
|
@ -118,6 +118,8 @@ st_table *rb_hash_tbl_raw(VALUE hash, const char *file, int line);
|
|||||||
#define RHASH_TBL_RAW(h) rb_hash_tbl_raw(h, __FILE__, __LINE__)
|
#define RHASH_TBL_RAW(h) rb_hash_tbl_raw(h, __FILE__, __LINE__)
|
||||||
MJIT_SYMBOL_EXPORT_END
|
MJIT_SYMBOL_EXPORT_END
|
||||||
|
|
||||||
|
VALUE rb_hash_compare_by_id(VALUE hash);
|
||||||
|
|
||||||
#if 0 /* for debug */
|
#if 0 /* for debug */
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
|
28
marshal.c
28
marshal.c
@ -30,6 +30,7 @@
|
|||||||
#include "internal/hash.h"
|
#include "internal/hash.h"
|
||||||
#include "internal/object.h"
|
#include "internal/object.h"
|
||||||
#include "internal/struct.h"
|
#include "internal/struct.h"
|
||||||
|
#include "internal/symbol.h"
|
||||||
#include "internal/util.h"
|
#include "internal/util.h"
|
||||||
#include "internal/vm.h"
|
#include "internal/vm.h"
|
||||||
#include "ruby/io.h"
|
#include "ruby/io.h"
|
||||||
@ -966,6 +967,10 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
|
|||||||
|
|
||||||
case T_HASH:
|
case T_HASH:
|
||||||
w_uclass(obj, rb_cHash, arg);
|
w_uclass(obj, rb_cHash, arg);
|
||||||
|
if (rb_hash_compare_by_id_p(obj)) {
|
||||||
|
w_byte(TYPE_UCLASS, arg);
|
||||||
|
w_symbol(rb_sym_intern_ascii_cstr("Hash"), arg);
|
||||||
|
}
|
||||||
if (NIL_P(RHASH_IFNONE(obj))) {
|
if (NIL_P(RHASH_IFNONE(obj))) {
|
||||||
w_byte(TYPE_HASH, arg);
|
w_byte(TYPE_HASH, arg);
|
||||||
}
|
}
|
||||||
@ -1702,11 +1707,20 @@ append_extmod(VALUE obj, VALUE extmod)
|
|||||||
(str)); \
|
(str)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
static VALUE r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type);
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod)
|
r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod)
|
||||||
{
|
{
|
||||||
VALUE v = Qnil;
|
|
||||||
int type = r_byte(arg);
|
int type = r_byte(arg);
|
||||||
|
return r_object_for(arg, partial, ivp, extmod, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type)
|
||||||
|
{
|
||||||
|
VALUE (*hash_new_with_size)(st_index_t) = rb_hash_new_with_size;
|
||||||
|
VALUE v = Qnil;
|
||||||
long id;
|
long id;
|
||||||
st_data_t link;
|
st_data_t link;
|
||||||
|
|
||||||
@ -1774,7 +1788,14 @@ r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod)
|
|||||||
if (FL_TEST(c, FL_SINGLETON)) {
|
if (FL_TEST(c, FL_SINGLETON)) {
|
||||||
rb_raise(rb_eTypeError, "singleton can't be loaded");
|
rb_raise(rb_eTypeError, "singleton can't be loaded");
|
||||||
}
|
}
|
||||||
v = r_object0(arg, partial, 0, extmod);
|
type = r_byte(arg);
|
||||||
|
if ((c == rb_cHash) &&
|
||||||
|
/* Hack for compare_by_identify */
|
||||||
|
(type == TYPE_HASH || type == TYPE_HASH_DEF)) {
|
||||||
|
hash_new_with_size = rb_ident_hash_new_with_size;
|
||||||
|
goto type_hash;
|
||||||
|
}
|
||||||
|
v = r_object_for(arg, partial, 0, extmod, type);
|
||||||
if (rb_special_const_p(v) || RB_TYPE_P(v, T_OBJECT) || RB_TYPE_P(v, T_CLASS)) {
|
if (rb_special_const_p(v) || RB_TYPE_P(v, T_OBJECT) || RB_TYPE_P(v, T_CLASS)) {
|
||||||
goto format_error;
|
goto format_error;
|
||||||
}
|
}
|
||||||
@ -1915,10 +1936,11 @@ r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod)
|
|||||||
|
|
||||||
case TYPE_HASH:
|
case TYPE_HASH:
|
||||||
case TYPE_HASH_DEF:
|
case TYPE_HASH_DEF:
|
||||||
|
type_hash:
|
||||||
{
|
{
|
||||||
long len = r_long(arg);
|
long len = r_long(arg);
|
||||||
|
|
||||||
v = rb_hash_new_with_size(len);
|
v = hash_new_with_size(len);
|
||||||
v = r_entry(v, arg);
|
v = r_entry(v, arg);
|
||||||
arg->readable += (len - 1) * 2;
|
arg->readable += (len - 1) * 2;
|
||||||
while (len--) {
|
while (len--) {
|
||||||
|
@ -870,4 +870,23 @@ class TestMarshal < Test::Unit::TestCase
|
|||||||
Marshal.load(s, :freeze.to_proc)
|
Marshal.load(s, :freeze.to_proc)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def _test_hash_compared_by_identity(h)
|
||||||
|
h.compare_by_identity
|
||||||
|
h["a" + "0"] = 1
|
||||||
|
h["a" + "0"] = 2
|
||||||
|
h = Marshal.load(Marshal.dump(h))
|
||||||
|
assert_predicate(h, :compare_by_identity?)
|
||||||
|
a = h.to_a
|
||||||
|
assert_equal([["a0", 1], ["a0", 2]], a.sort)
|
||||||
|
assert_not_same(a[1][0], a[0][0])
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_hash_compared_by_identity
|
||||||
|
_test_hash_compared_by_identity(Hash.new)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_hash_default_compared_by_identity
|
||||||
|
_test_hash_compared_by_identity(Hash.new(true))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user