Since 4ea42f7 (#4846), two programs that walk an array of one user class fail. Both work on bb78dbb, the commit before it.
1. A store into the block parameter segfaults.
class H
def initialize; @h = {}; end
def []=(k, v); @h[k] = v; end
def [](k); @h[k]; end
end
a = [H.new]
a.each { |r| r["X-A"] = "7" }
p a[0]["X-A"]
CRuby prints "7". 4ea42f7 segfaults. bb78dbb printed nil, which was also wrong: the store never reached H#[]=. The emitted C declares the block parameter sp_StrStrHash *lv_r and binds each sp_H * element into it. With reverse_each, each_entry or each_with_index in place of each it segfaults too, and with map or collect the C build fails.
2. Using the walk's value fails the C build.
class Hd
attr_reader :n
def initialize(n); @n = n; end
end
a = [Hd.new(1), Hd.new(2)]
y = a.each_with_index { |r, i| r.n }
p y.size
x = a.each { |r| break r if r.n == 2 }
p x.n
CRuby and bb78dbb print 2 and 2. 4ea42f7 fails the C build with incompatible pointer types assigning to 'sp_PolyArray *' from 'sp_PtrArray *'.
What we tried for the first one, in case it helps. Giving the walk's block parameter the element class in infer_block_params (via ty_array_elem of the narrowed receiver) fixes the program above, but breaks blocks that reassign the parameter, which work on 4ea42f7: a.each { |r| r = r.x; p r } and a.each_with_index { |r, i| r = [i]; p r } fail the C build, and r = nil followed by r.is_a?(Pt) answers true. Keeping the element boxed instead reaches the boxed x[k] = v path, which does not call a user class's []= at all (the nil bb78dbb printed).
Since 4ea42f7 (#4846), two programs that walk an array of one user class fail. Both work on bb78dbb, the commit before it.
1. A store into the block parameter segfaults.
CRuby prints
"7". 4ea42f7 segfaults. bb78dbb printednil, which was also wrong: the store never reachedH#[]=. The emitted C declares the block parametersp_StrStrHash *lv_rand binds eachsp_H *element into it. Withreverse_each,each_entryoreach_with_indexin place ofeachit segfaults too, and withmaporcollectthe C build fails.2. Using the walk's value fails the C build.
CRuby and bb78dbb print
2and2. 4ea42f7 fails the C build withincompatible pointer types assigning to 'sp_PolyArray *' from 'sp_PtrArray *'.What we tried for the first one, in case it helps. Giving the walk's block parameter the element class in
infer_block_params(viaty_array_elemof the narrowed receiver) fixes the program above, but breaks blocks that reassign the parameter, which work on 4ea42f7:a.each { |r| r = r.x; p r }anda.each_with_index { |r, i| r = [i]; p r }fail the C build, andr = nilfollowed byr.is_a?(Pt)answers true. Keeping the element boxed instead reaches the boxedx[k] = vpath, which does not call a user class's[]=at all (thenilbb78dbb printed).