summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--array.c13
-rw-r--r--enum.c16
-rw-r--r--test/ruby/test_array.rb12
-rw-r--r--test/ruby/test_enum.rb18
5 files changed, 47 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index d5223fa02d..a6a57ccdbe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Mon Dec 23 12:42:13 2013 Marc-Andre Lafortune <ruby-core@marc-andre.ca>
+
+ * array.c: Have to_h raise on elements that are not key-value pairs
+ [#9239]
+
+ * enum.c: ditto
+
Mon Dec 23 05:01:55 2013 Zachary Scott <e@zzak.io>
* doc/syntax/methods.rdoc: [DOC] Added example for underscore
diff --git a/array.c b/array.c
index 0241d72b5f..45713c55b0 100644
--- a/array.c
+++ b/array.c
@@ -2130,8 +2130,7 @@ rb_ary_to_a(VALUE ary)
* ary.to_h -> hash
*
* Returns the result of interpreting <i>ary</i> as an array of
- * <tt>[key, value]</tt> pairs. Elements other than pairs of
- * values are ignored.
+ * <tt>[key, value]</tt> pairs.
*
* [[:foo, :bar], [1, 2]].to_h
* # => {:foo => :bar, 1 => 2}
@@ -2144,9 +2143,15 @@ rb_ary_to_h(VALUE ary)
VALUE hash = rb_hash_new();
for (i=0; i<RARRAY_LEN(ary); i++) {
VALUE key_value_pair = rb_check_array_type(rb_ary_elt(ary, i));
- if (!NIL_P(key_value_pair) && (RARRAY_LEN(key_value_pair) == 2)) {
- rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
+ if (NIL_P(key_value_pair)) {
+ rb_raise(rb_eTypeError, "wrong element type %s at %ld (expected array)",
+ rb_builtin_class_name(rb_ary_elt(ary, i)), i);
}
+ if (RARRAY_LEN(key_value_pair) != 2) {
+ rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
+ i, RARRAY_LEN(key_value_pair));
+ }
+ rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
}
return hash;
}
diff --git a/enum.c b/enum.c
index 6e40b50c4d..e37ff16c5d 100644
--- a/enum.c
+++ b/enum.c
@@ -512,12 +512,19 @@ enum_to_a(int argc, VALUE *argv, VALUE obj)
static VALUE
enum_to_h_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
{
+ VALUE key_value_pair;
ENUM_WANT_SVALUE();
rb_thread_check_ints();
- i = rb_check_array_type(i);
- if (!NIL_P(i) && RARRAY_LEN(i) == 2) {
- rb_hash_aset(hash, RARRAY_AREF(i, 0), RARRAY_AREF(i, 1));
+ key_value_pair = rb_check_array_type(i);
+ if (NIL_P(key_value_pair)) {
+ rb_raise(rb_eTypeError, "wrong element type %s (expected array)",
+ rb_builtin_class_name(i));
}
+ if (RARRAY_LEN(key_value_pair) != 2) {
+ rb_raise(rb_eArgError, "element has wrong array length (expected 2, was %ld)",
+ RARRAY_LEN(key_value_pair));
+ }
+ rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
return Qnil;
}
@@ -526,8 +533,7 @@ enum_to_h_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
* enum.to_h(*args) -> hash
*
* Returns the result of interpreting <i>enum</i> as a list of
- * <tt>[key, value]</tt> pairs. Elements other than pairs of
- * values are ignored.
+ * <tt>[key, value]</tt> pairs.
*
* %i[hello world].each_with_index.to_h
* # => {:hello => 0, :world => 1}
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index 526fcabb1b..b648c404ed 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -1467,12 +1467,18 @@ class TestArray < Test::Unit::TestCase
end
array = [
[:key, :value],
- [:ignore_me],
- [:ignore, :me, :too],
- :ignore_me,
kvp,
]
assert_equal({key: :value, obtained: :via_to_ary}, array.to_h)
+
+ e = assert_raise(TypeError) {
+ [[:first_one, :ok], :not_ok].to_h
+ }
+ assert_equal "wrong element type Symbol at 1 (expected array)", e.message
+ e = assert_raise(ArgumentError) {
+ [[:first_one, :ok], [1, 2], [:not_ok]].to_h
+ }
+ assert_equal "wrong array length at 2 (expected 2, was 1)", e.message
end
def test_uniq
diff --git a/test/ruby/test_enum.rb b/test/ruby/test_enum.rb
index b86ae274d1..3ee6846b33 100644
--- a/test/ruby/test_enum.rb
+++ b/test/ruby/test_enum.rb
@@ -104,17 +104,11 @@ class TestEnumerable < Test::Unit::TestCase
end
def test_to_h
- assert_equal({}, @obj.to_h)
obj = Object.new
def obj.each(*args)
- yield args
+ yield *args
yield [:key, :value]
- yield [:ignore_me]
- yield [:ignore, :me, :too]
yield :other_key, :other_value
- yield :ignore_me
- yield :ignore, :me, :too
- yield
kvp = Object.new
def kvp.to_ary
[:obtained, :via_to_ary]
@@ -128,6 +122,16 @@ class TestEnumerable < Test::Unit::TestCase
:other_key => :other_value,
:obtained => :via_to_ary,
}, obj.to_h(:hello, :world))
+
+ e = assert_raise(TypeError) {
+ obj.to_h(:not_an_array)
+ }
+ assert_equal "wrong element type Symbol (expected array)", e.message
+
+ e = assert_raise(ArgumentError) {
+ obj.to_h([1])
+ }
+ assert_equal "element has wrong array length (expected 2, was 1)", e.message
end
def test_inject