summaryrefslogtreecommitdiff
path: root/class.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-14 11:58:17 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-14 11:58:17 +0000
commit37279d15468ec5d5873e9a5fea49cd6323891fa6 (patch)
tree0550c01e46a0c04ce26e1177763dc97000eaee0d /class.c
parent31bfe0fe86433beddfec2b2bdba69dfda1775f8d (diff)
non-symbol keys in kwargs
* class.c (separate_symbol): [EXPERIMENTAL] non-symbol key in keyword arguments hash causes an exception now. c.f. https://twitter.com/yukihiro_matz/status/1022287578995646464 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64358 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'class.c')
-rw-r--r--class.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/class.c b/class.c
index cb47849e96..b77974fdf2 100644
--- a/class.c
+++ b/class.c
@@ -1814,33 +1814,57 @@ unknown_keyword_error(VALUE hash, const ID *table, int keywords)
rb_keyword_error("unknown", rb_hash_keys(hash));
}
+struct extract_keywords {
+ VALUE kwdhash, nonsymkey;
+};
+
static int
separate_symbol(st_data_t key, st_data_t value, st_data_t arg)
{
- VALUE *kwdhash = (VALUE *)arg;
+ struct extract_keywords *argp = (struct extract_keywords *)arg;
+ VALUE k = (VALUE)key, v = (VALUE)value;
- if (!SYMBOL_P(key)) kwdhash++;
- if (!*kwdhash) *kwdhash = rb_hash_new();
- rb_hash_aset(*kwdhash, (VALUE)key, (VALUE)value);
+ if (argp->kwdhash) {
+ if (UNLIKELY(!SYMBOL_P(k))) {
+ argp->nonsymkey = k;
+ return ST_STOP;
+ }
+ }
+ else if (SYMBOL_P(k)) {
+ if (UNLIKELY(argp->nonsymkey != Qundef)) {
+ argp->kwdhash = Qnil;
+ return ST_STOP;
+ }
+ argp->kwdhash = rb_hash_new();
+ }
+ else {
+ if (argp->nonsymkey == Qundef)
+ argp->nonsymkey = k;
+ return ST_CONTINUE;
+ }
+ rb_hash_aset(argp->kwdhash, k, v);
return ST_CONTINUE;
}
VALUE
rb_extract_keywords(VALUE *orighash)
{
- VALUE parthash[2] = {0, 0};
+ struct extract_keywords arg = {0, Qundef};
VALUE hash = *orighash;
if (RHASH_EMPTY_P(hash)) {
*orighash = 0;
return hash;
}
- st_foreach(rb_hash_tbl_raw(hash), separate_symbol, (st_data_t)&parthash);
- *orighash = parthash[1];
- if (parthash[1] && RBASIC_CLASS(hash) != rb_cHash) {
- RBASIC_SET_CLASS(parthash[1], RBASIC_CLASS(hash));
+ st_foreach(rb_hash_tbl_raw(hash), separate_symbol, (st_data_t)&arg);
+ if (arg.kwdhash) {
+ if (arg.nonsymkey != Qundef) {
+ rb_raise(rb_eArgError, "non-symbol key in keyword arguments: %+"PRIsVALUE,
+ arg.nonsymkey);
+ }
+ *orighash = 0;
}
- return parthash[0];
+ return arg.kwdhash;
}
int