aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-08-30 21:56:50 -0700
committerJeremy Evans <code@jeremyevans.net>2019-08-30 21:56:50 -0700
commitec6206a81a1d61efe5bda69ab704c09e75033c01 (patch)
tree0bab6c1fb1ba657b9edcbc6c235211f3160c800b
parent3463e83192215c36bdcebad8be907eaa09593a41 (diff)
downloadruby-ec6206a81a1d61efe5bda69ab704c09e75033c01.tar.gz
Use more accurate source location in keyword argument separation warnings
This shows locations in places it didn't before, such as for proc calls, and fixes the location for super calls. This requires making iseq_location non-static and MJIT exported, which I hope will not cause problems.
-rw-r--r--proc.c2
-rw-r--r--test/ruby/test_keyword.rb8
-rw-r--r--vm_args.c28
3 files changed, 17 insertions, 21 deletions
diff --git a/proc.c b/proc.c
index 8f51ff10eb..4d180f897e 100644
--- a/proc.c
+++ b/proc.c
@@ -1183,7 +1183,7 @@ rb_proc_get_iseq(VALUE self, int *is_proc)
return NULL;
}
-static VALUE
+MJIT_FUNC_EXPORTED VALUE
iseq_location(const rb_iseq_t *iseq)
{
VALUE loc[2];
diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb
index 2630983a71..6212d582f5 100644
--- a/test/ruby/test_keyword.rb
+++ b/test/ruby/test_keyword.rb
@@ -308,18 +308,18 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(expect, rest_keyrest(*expect), bug7665)
end
pr = proc {|*args, **opt| next *args, opt}
- assert_warn(/The last argument for `call' is used as the keyword parameter/) do
+ assert_warn(/The last argument for `call' .* is used as the keyword parameter/) do
assert_equal(expect, pr.call(*expect), bug7665)
end
- assert_warn(/The last argument for `call' is used as the keyword parameter/) do
+ assert_warn(/The last argument for `call' .* is used as the keyword parameter/) do
assert_equal(expect, pr.call(expect), bug8463)
end
pr = proc {|a, *b, **opt| next a, *b, opt}
- assert_warn(/The last argument for `call' is used as the keyword parameter/) do
+ assert_warn(/The last argument for `call' .* is used as the keyword parameter/) do
assert_equal(expect, pr.call(expect), bug8463)
end
pr = proc {|a, **opt| next a, opt}
- assert_warn(/The last argument for `call' is used as the keyword parameter/) do
+ assert_warn(/The last argument for `call' .* is used as the keyword parameter/) do
assert_equal(expect.values_at(0, -1), pr.call(expect), bug8463)
end
end
diff --git a/vm_args.c b/vm_args.c
index f8d329c993..7db1d3e989 100644
--- a/vm_args.c
+++ b/vm_args.c
@@ -579,17 +579,13 @@ ignore_keyword_hash_p(VALUE keyword_hash, const rb_iseq_t * const iseq) {
return 0;
}
-static inline VALUE
-get_loc(struct rb_calling_info *calling, const struct rb_call_info *ci)
-{
- return rb_obj_method_location(calling->recv, ci->mid);
-}
+VALUE iseq_location(const rb_iseq_t *iseq);
static inline void
-rb_warn_keyword_to_last_hash(struct rb_calling_info *calling, const struct rb_call_info *ci)
+rb_warn_keyword_to_last_hash(struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq)
{
if (calling->recv == Qundef) return;
- VALUE loc = get_loc(calling, ci);
+ VALUE loc = iseq_location(iseq);
if (NIL_P(loc)) {
rb_warn("The keyword argument for `%s' is passed as the last hash parameter", rb_id2name(ci->mid));
}
@@ -600,10 +596,10 @@ rb_warn_keyword_to_last_hash(struct rb_calling_info *calling, const struct rb_ca
}
static inline void
-rb_warn_split_last_hash_to_keyword(struct rb_calling_info *calling, const struct rb_call_info *ci)
+rb_warn_split_last_hash_to_keyword(struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq)
{
if (calling->recv == Qundef) return;
- VALUE loc = get_loc(calling, ci);
+ VALUE loc = iseq_location(iseq);
if (NIL_P(loc)) {
rb_warn("The last argument for `%s' is split into positional and keyword parameters", rb_id2name(ci->mid));
}
@@ -614,10 +610,10 @@ rb_warn_split_last_hash_to_keyword(struct rb_calling_info *calling, const struct
}
static inline void
-rb_warn_last_hash_to_keyword(struct rb_calling_info *calling, const struct rb_call_info *ci)
+rb_warn_last_hash_to_keyword(struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq)
{
if (calling->recv == Qundef) return;
- VALUE loc = get_loc(calling, ci);
+ VALUE loc = iseq_location(iseq);
if (NIL_P(loc)) {
rb_warn("The last argument for `%s' is used as the keyword parameter", rb_id2name(ci->mid));
}
@@ -770,10 +766,10 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
}
else if (check_only_symbol) {
if (keyword_hash != Qnil) {
- rb_warn_split_last_hash_to_keyword(calling, ci);
+ rb_warn_split_last_hash_to_keyword(calling, ci, iseq);
}
else {
- rb_warn_keyword_to_last_hash(calling, ci);
+ rb_warn_keyword_to_last_hash(calling, ci, iseq);
}
}
}
@@ -784,16 +780,16 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
*/
if (ec->cfp->iseq) {
/* called from Ruby level */
- rb_warn_last_hash_to_keyword(calling, ci);
+ rb_warn_last_hash_to_keyword(calling, ci, iseq);
}
given_argc--;
}
else if (keyword_hash != Qnil && ec->cfp->iseq) {
- rb_warn_split_last_hash_to_keyword(calling, ci);
+ rb_warn_split_last_hash_to_keyword(calling, ci, iseq);
}
}
else if (given_argc == min_argc && kw_flag) {
- rb_warn_keyword_to_last_hash(calling, ci);
+ rb_warn_keyword_to_last_hash(calling, ci, iseq);
}
}