mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	Make Symbol#to_proc calls handle keyword arguments
Make rb_sym_proc_call take a flag for whether a keyword argument is used, and use the new rb_funcall_with_block_kw function to pass that information.
This commit is contained in:
		
							parent
							
								
									38dae1d510
								
							
						
					
					
						commit
						6f9b86616a
					
				
					 4 changed files with 77 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -2140,7 +2140,7 @@ VALUE rb_str_initialize(VALUE str, const char *ptr, long len, rb_encoding *enc);
 | 
			
		|||
#define is_ascii_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT)
 | 
			
		||||
#define is_broken_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN)
 | 
			
		||||
size_t rb_str_memsize(VALUE);
 | 
			
		||||
VALUE rb_sym_proc_call(ID mid, int argc, const VALUE *argv, VALUE passed_proc);
 | 
			
		||||
VALUE rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc);
 | 
			
		||||
VALUE rb_sym_to_proc(VALUE sym);
 | 
			
		||||
char *rb_str_to_cstr(VALUE str);
 | 
			
		||||
VALUE rb_str_eql(VALUE str1, VALUE str2);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								string.c
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								string.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -10887,7 +10887,7 @@ sym_to_sym(VALUE sym)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
MJIT_FUNC_EXPORTED VALUE
 | 
			
		||||
rb_sym_proc_call(ID mid, int argc, const VALUE *argv, VALUE passed_proc)
 | 
			
		||||
rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc)
 | 
			
		||||
{
 | 
			
		||||
    VALUE obj;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -10895,7 +10895,7 @@ rb_sym_proc_call(ID mid, int argc, const VALUE *argv, VALUE passed_proc)
 | 
			
		|||
	rb_raise(rb_eArgError, "no receiver given");
 | 
			
		||||
    }
 | 
			
		||||
    obj = argv[0];
 | 
			
		||||
    return rb_funcall_with_block(obj, mid, argc - 1, argv + 1, passed_proc);
 | 
			
		||||
    return rb_funcall_with_block_kw(obj, mid, argc - 1, argv + 1, passed_proc, kw_splat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -447,6 +447,79 @@ class TestKeywordArguments < Test::Unit::TestCase
 | 
			
		|||
    assert_equal([1, h3], c.send(:m, **h3))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_sym_proc_kwsplat
 | 
			
		||||
    kw = {}
 | 
			
		||||
    h = {'a'=>1}
 | 
			
		||||
    h2 = {'a'=>1}
 | 
			
		||||
    h3 = {'a'=>1, :a=>1}
 | 
			
		||||
 | 
			
		||||
    c = Object.new
 | 
			
		||||
    def c.m(*args)
 | 
			
		||||
      args
 | 
			
		||||
    end
 | 
			
		||||
    assert_equal([], :m.to_proc.call(c, **{}))
 | 
			
		||||
    assert_equal([], :m.to_proc.call(c, **kw))
 | 
			
		||||
    assert_equal([h], :m.to_proc.call(c, **h))
 | 
			
		||||
    assert_equal([h2], :m.to_proc.call(c, **h2))
 | 
			
		||||
    assert_equal([h3], :m.to_proc.call(c, **h3))
 | 
			
		||||
 | 
			
		||||
    c.singleton_class.remove_method(:m)
 | 
			
		||||
    def c.m; end
 | 
			
		||||
    assert_nil(:m.to_proc.call(c, **{}))
 | 
			
		||||
    assert_nil(:m.to_proc.call(c, **kw))
 | 
			
		||||
    assert_raise(ArgumentError) { :m.to_proc.call(c, **h) }
 | 
			
		||||
    assert_raise(ArgumentError) { :m.to_proc.call(c, **h2) }
 | 
			
		||||
    assert_raise(ArgumentError) { :m.to_proc.call(c, **h3) }
 | 
			
		||||
 | 
			
		||||
    c.singleton_class.remove_method(:m)
 | 
			
		||||
    def c.m(args)
 | 
			
		||||
      args
 | 
			
		||||
    end
 | 
			
		||||
    assert_raise(ArgumentError) { :m.to_proc.call(c, **{}) }
 | 
			
		||||
    assert_raise(ArgumentError) { :m.to_proc.call(c, **kw) }
 | 
			
		||||
    assert_equal(h, :m.to_proc.call(c, **h))
 | 
			
		||||
    assert_equal(h2, :m.to_proc.call(c, **h2))
 | 
			
		||||
    assert_equal(h3, :m.to_proc.call(c, **h3))
 | 
			
		||||
 | 
			
		||||
    c.singleton_class.remove_method(:m)
 | 
			
		||||
    def c.m(**args)
 | 
			
		||||
      args
 | 
			
		||||
    end
 | 
			
		||||
    assert_equal(kw, :m.to_proc.call(c, **{}))
 | 
			
		||||
    assert_equal(kw, :m.to_proc.call(c, **kw))
 | 
			
		||||
    assert_equal(h, :m.to_proc.call(c, **h))
 | 
			
		||||
    assert_equal(h2, :m.to_proc.call(c, **h2))
 | 
			
		||||
    assert_equal(h3, :m.to_proc.call(c, **h3))
 | 
			
		||||
 | 
			
		||||
    c.singleton_class.remove_method(:m)
 | 
			
		||||
    def c.m(arg, **args)
 | 
			
		||||
      [arg, args]
 | 
			
		||||
    end
 | 
			
		||||
    assert_raise(ArgumentError) { :m.to_proc.call(c, **{}) }
 | 
			
		||||
    assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do
 | 
			
		||||
      assert_equal([kw, kw], :m.to_proc.call(c, **kw))
 | 
			
		||||
    end
 | 
			
		||||
    assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do
 | 
			
		||||
      assert_equal([h, kw], :m.to_proc.call(c, **h))
 | 
			
		||||
    end
 | 
			
		||||
    assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do
 | 
			
		||||
      assert_equal([h2, kw], :m.to_proc.call(c, **h2))
 | 
			
		||||
    end
 | 
			
		||||
    assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do
 | 
			
		||||
      assert_equal([h3, kw], :m.to_proc.call(c, **h3))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    c.singleton_class.remove_method(:m)
 | 
			
		||||
    def c.m(arg=1, **args)
 | 
			
		||||
      [arg=1, args]
 | 
			
		||||
    end
 | 
			
		||||
    assert_equal([1, kw], :m.to_proc.call(c, **{}))
 | 
			
		||||
    assert_equal([1, kw], :m.to_proc.call(c, **kw))
 | 
			
		||||
    assert_equal([1, h], :m.to_proc.call(c, **h))
 | 
			
		||||
    assert_equal([1, h2], :m.to_proc.call(c, **h2))
 | 
			
		||||
    assert_equal([1, h3], :m.to_proc.call(c, **h3))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_method_missing_kwsplat
 | 
			
		||||
    kw = {}
 | 
			
		||||
    h = {'a'=>1}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2884,8 +2884,7 @@ vm_yield_with_cfunc(rb_execution_context_t *ec,
 | 
			
		|||
static VALUE
 | 
			
		||||
vm_yield_with_symbol(rb_execution_context_t *ec,  VALUE symbol, int argc, const VALUE *argv, int kw_splat, VALUE block_handler)
 | 
			
		||||
{
 | 
			
		||||
    /* XXX: need to pass kw_splat? */
 | 
			
		||||
    return rb_sym_proc_call(SYM2ID(symbol), argc, argv, rb_vm_bh_to_procval(ec, block_handler));
 | 
			
		||||
    return rb_sym_proc_call(SYM2ID(symbol), argc, argv, kw_splat, rb_vm_bh_to_procval(ec, block_handler));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue