mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	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 
				
			
			
			
		
		
					 5 changed files with 48 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -7547,6 +7547,7 @@ marshal.$(OBJEXT): $(top_srcdir)/internal/serial.h
 | 
			
		|||
marshal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
 | 
			
		||||
marshal.$(OBJEXT): $(top_srcdir)/internal/string.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/vm.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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE rb_hash_compare_by_id(VALUE hash);
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
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}
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
VALUE
 | 
			
		||||
rb_hash_compare_by_id(VALUE hash)
 | 
			
		||||
{
 | 
			
		||||
    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__)
 | 
			
		||||
MJIT_SYMBOL_EXPORT_END
 | 
			
		||||
 | 
			
		||||
VALUE rb_hash_compare_by_id(VALUE hash);
 | 
			
		||||
 | 
			
		||||
#if 0 /* for debug */
 | 
			
		||||
 | 
			
		||||
static inline bool
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										28
									
								
								marshal.c
									
										
									
									
									
								
							
							
						
						
									
										28
									
								
								marshal.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -30,6 +30,7 @@
 | 
			
		|||
#include "internal/hash.h"
 | 
			
		||||
#include "internal/object.h"
 | 
			
		||||
#include "internal/struct.h"
 | 
			
		||||
#include "internal/symbol.h"
 | 
			
		||||
#include "internal/util.h"
 | 
			
		||||
#include "internal/vm.h"
 | 
			
		||||
#include "ruby/io.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -966,6 +967,10 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
 | 
			
		|||
 | 
			
		||||
	  case T_HASH:
 | 
			
		||||
	    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))) {
 | 
			
		||||
		w_byte(TYPE_HASH, arg);
 | 
			
		||||
	    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1702,11 +1707,20 @@ append_extmod(VALUE obj, VALUE extmod)
 | 
			
		|||
		 (str)); \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
static VALUE r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type);
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod)
 | 
			
		||||
{
 | 
			
		||||
    VALUE v = Qnil;
 | 
			
		||||
    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;
 | 
			
		||||
    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)) {
 | 
			
		||||
		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)) {
 | 
			
		||||
                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_DEF:
 | 
			
		||||
      type_hash:
 | 
			
		||||
	{
 | 
			
		||||
	    long len = r_long(arg);
 | 
			
		||||
 | 
			
		||||
	    v = rb_hash_new_with_size(len);
 | 
			
		||||
	    v = hash_new_with_size(len);
 | 
			
		||||
	    v = r_entry(v, arg);
 | 
			
		||||
	    arg->readable += (len - 1) * 2;
 | 
			
		||||
	    while (len--) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -870,4 +870,23 @@ class TestMarshal < Test::Unit::TestCase
 | 
			
		|||
      Marshal.load(s, :freeze.to_proc)
 | 
			
		||||
    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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue