File tree Expand file tree Collapse file tree 3 files changed +38
-2
lines changed
Expand file tree Collapse file tree 3 files changed +38
-2
lines changed Original file line number Diff line number Diff line change @@ -13032,6 +13032,7 @@ proc.$(OBJEXT): $(top_srcdir)/internal/compilers.h
1303213032proc.$(OBJEXT): $(top_srcdir)/internal/error.h
1303313033proc.$(OBJEXT): $(top_srcdir)/internal/eval.h
1303413034proc.$(OBJEXT): $(top_srcdir)/internal/gc.h
13035+ proc.$(OBJEXT): $(top_srcdir)/internal/hash.h
1303513036proc.$(OBJEXT): $(top_srcdir)/internal/imemo.h
1303613037proc.$(OBJEXT): $(top_srcdir)/internal/object.h
1303713038proc.$(OBJEXT): $(top_srcdir)/internal/proc.h
Original file line number Diff line number Diff line change 1515#include "internal/error.h"
1616#include "internal/eval.h"
1717#include "internal/gc.h"
18+ #include "internal/hash.h"
1819#include "internal/object.h"
1920#include "internal/proc.h"
2021#include "internal/symbol.h"
@@ -1437,8 +1438,24 @@ rb_hash_proc(st_index_t hash, VALUE prc)
14371438{
14381439 rb_proc_t * proc ;
14391440 GetProcPtr (prc , proc );
1440- hash = rb_hash_uint (hash , (st_index_t )proc -> block .as .captured .code .val );
1441- hash = rb_hash_uint (hash , (st_index_t )proc -> block .as .captured .self );
1441+
1442+ switch (vm_block_type (& proc -> block )) {
1443+ case block_type_iseq :
1444+ hash = rb_st_hash_uint (hash , (st_index_t )proc -> block .as .captured .code .iseq -> body );
1445+ break ;
1446+ case block_type_ifunc :
1447+ hash = rb_st_hash_uint (hash , (st_index_t )proc -> block .as .captured .code .ifunc -> func );
1448+ break ;
1449+ case block_type_symbol :
1450+ hash = rb_st_hash_uint (hash , rb_any_hash (proc -> block .as .symbol ));
1451+ break ;
1452+ case block_type_proc :
1453+ hash = rb_st_hash_uint (hash , rb_any_hash (proc -> block .as .proc ));
1454+ break ;
1455+ default :
1456+ rb_bug ("rb_hash_proc: unknown block type %d" , vm_block_type (& proc -> block ));
1457+ }
1458+
14421459 return rb_hash_uint (hash , (st_index_t )proc -> block .as .captured .ep );
14431460}
14441461
Original file line number Diff line number Diff line change @@ -168,6 +168,24 @@ def self.capture(&block)
168168 assert_operator ( procs . map ( &:hash ) . uniq . size , :>= , 500 )
169169 end
170170
171+ def test_hash_does_not_change_after_compaction
172+ # [Bug #20853]
173+ [
174+ "proc {}" , # iseq backed proc
175+ "{}.to_proc" , # ifunc backed proc
176+ ":hello.to_proc" , # symbol backed proc
177+ ] . each do |proc |
178+ assert_separately ( [ ] , <<~RUBY )
179+ p1 = #{ proc }
180+ hash = p1.hash
181+
182+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
183+
184+ assert_equal(hash, p1.hash, "proc is `#{ proc } `")
185+ RUBY
186+ end
187+ end
188+
171189 def test_block_par
172190 assert_equal ( 10 , Proc . new { |&b | b . call ( 10 ) } . call { |x | x } )
173191 assert_equal ( 12 , Proc . new { |a , &b | b . call ( a ) } . call ( 12 ) { |x | x } )
You can’t perform that action at this time.
0 commit comments