Project

General

Profile

Bug #15114 » fix_symbol_to_proc.patch

&:hoge が refinements に反映されるように修正 - osyo (manga osyo), 09/13/2018 08:13 AM

View differences:

method.h
194 194
const rb_method_entry_t *rb_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class);
195 195
const rb_method_entry_t *rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me);
196 196
RUBY_SYMBOL_EXPORT_BEGIN
197
const rb_callable_method_entry_t *rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me);
197 198
const rb_method_entry_t *rb_resolve_me_location(const rb_method_entry_t *, VALUE[5]);
198 199
RUBY_SYMBOL_EXPORT_END
199 200

  
test/ruby/test_symbol.rb
161 161
    assert_equal(1, first, bug11594)
162 162
  end
163 163

  
164
  class TestToPRocArgWithRefinements; end
165
  def _test_to_proc_arg_with_refinements_call(&block)
166
    block.call TestToPRocArgWithRefinements.new
167
  end
168
  using Module.new {
169
    refine TestToPRocArgWithRefinements do
170
      def hoge
171
        :hoge
172
      end
173
    end
174
  }
175
  def test_to_proc_arg_with_refinements
176
    assert_equal(:hoge, _test_to_proc_arg_with_refinements_call(&:hoge))
177
  end
178

  
179
  using Module.new {
180
    refine TestToPRocArgWithRefinements do
181
      def hoge
182
        :hogehoge
183
      end
184
    end
185
  }
186
  def test_to_proc_arg_with_refinements_override
187
    assert_equal(:hogehoge, _test_to_proc_arg_with_refinements_call(&:hoge))
188
  end
189

  
164 190
  private def return_from_proc
165 191
    Proc.new { return 1 }.tap(&:call)
166 192
  end
vm_args.c
851 851
    ID mid;
852 852
    const rb_callable_method_entry_t *me;
853 853
    rb_execution_context_t *ec;
854
    const VALUE symbol = RARRAY_AREF(callback_arg, 0);
855
    const VALUE refinements = RARRAY_AREF(callback_arg, 1);
854 856

  
855 857
    if (argc-- < 1) {
856 858
	rb_raise(rb_eArgError, "no receiver given");
857 859
    }
858 860
    obj = *argv++;
859
    mid = SYM2ID(callback_arg);
860
    me = rb_callable_method_entry_with_refinements(CLASS_OF(obj), mid, NULL);
861

  
862
    mid = SYM2ID(symbol);
863
    me = rb_resolve_refined_method_callable(refinements, (const rb_callable_method_entry_t *)rb_method_entry(CLASS_OF(obj), mid));
864

  
861 865
    ec = GET_EC();
862 866
    if (!NIL_P(blockarg)) {
863 867
	vm_passed_block_handler_set(ec, blockarg);
......
885 889
	    const rb_cref_t *cref = vm_env_cref(reg_cfp->ep);
886 890
	    if (cref && !NIL_P(cref->refinements)) {
887 891
		VALUE ref = cref->refinements;
888
		VALUE func = rb_hash_lookup(ref, block_code);
889
		if (NIL_P(func)) {
890
		    /* TODO: limit cached funcs */
891
		    func = rb_func_proc_new(refine_sym_proc_call, block_code);
892
		    rb_hash_aset(ref, block_code, func);
893
		}
892
		VALUE callback_arg = rb_ary_new_from_args(2, block_code, ref);
893
		VALUE func = rb_func_proc_new(refine_sym_proc_call, callback_arg);
894 894
		block_code = func;
895 895
	    }
896 896
            return block_code;
vm_method.c
963 963
    return resolve_refined_method(refinements, me, NULL);
964 964
}
965 965

  
966
static const rb_callable_method_entry_t *
966
const rb_callable_method_entry_t *
967 967
rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me)
968 968
{
969 969
    VALUE defined_class = me->defined_class;