Skip to content

Walking a narrowed object array: a segfault and a C build failure since 4ea42f77 #4879

Description

@blacktm

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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions