[前][次][番号順一覧][スレッド一覧]

ruby-changes:72902

From: Jeremy <ko1@a...>
Date: Thu, 11 Aug 2022 19:17:04 +0900 (JST)
Subject: [ruby-changes:72902] cfb9624460 (master): Fix Array#[] with ArithmeticSequence with negative steps (#5739)

https://git.ruby-lang.org/ruby.git/commit/?id=cfb9624460

From cfb9624460a295e4e1723301486d89058c228e07 Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Thu, 11 Aug 2022 03:16:49 -0700
Subject: Fix Array#[] with ArithmeticSequence with negative steps (#5739)

* Fix Array#[] with ArithmeticSequence with negative steps

Previously, Array#[] when called with an ArithmeticSequence
with a negative step did not handle all cases correctly,
especially cases involving infinite ranges, inverted ranges,
and/or exclusive ends.

Fixes [Bug #18247]

* Add Array#slice tests for ArithmeticSequence with negative step to test_array

Add tests of rb_arithmetic_sequence_beg_len_step C-API function.

* Fix ext/-test-/arith_seq/beg_len_step/depend

* Rename local variables

* Fix a variable name

Co-authored-by: Kenta Murata <3959+mrkn@u...>
---
 array.c                                            |   5 +-
 enumerator.c                                       |   7 +
 ext/-test-/arith_seq/beg_len_step/beg_len_step.c   |  19 +++
 ext/-test-/arith_seq/beg_len_step/depend           | 161 +++++++++++++++++++++
 ext/-test-/arith_seq/beg_len_step/extconf.rb       |   2 +
 spec/ruby/core/array/shared/slice.rb               |  96 ++++++++++++
 .../-ext-/arith_seq/test_arith_seq_beg_len_step.rb |  52 +++++++
 test/ruby/test_array.rb                            |  90 ++++++++++++
 8 files changed, 431 insertions(+), 1 deletion(-)
 create mode 100644 ext/-test-/arith_seq/beg_len_step/beg_len_step.c
 create mode 100644 ext/-test-/arith_seq/beg_len_step/depend
 create mode 100644 ext/-test-/arith_seq/beg_len_step/extconf.rb
 create mode 100644 test/-ext-/arith_seq/test_arith_seq_beg_len_step.rb

diff --git a/array.c b/array.c
index b2ebf3c0e9..793a53f17b 100644
--- a/array.c
+++ b/array.c
@@ -1373,13 +1373,16 @@ ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step) https://github.com/ruby/ruby/blob/trunk/array.c#L1373
     const VALUE *values = RARRAY_CONST_PTR_TRANSIENT(ary);
     const long orig_len = len;
 
-    if ((step > 0 && step >= len) || (step < 0 && (step < -len))) {
+    if (step > 0 && step >= len) {
         VALUE result = ary_new(klass, 1);
         VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
         RB_OBJ_WRITE(result, ptr, values[offset]);
         ARY_SET_EMBED_LEN(result, 1);
         return result;
     }
+    else if (step < 0 && step < -len) {
+        step = -len;
+    }
 
     long ustep = (step < 0) ? -step : step;
     len = (len + ustep - 1) / ustep;
diff --git a/enumerator.c b/enumerator.c
index d7546ee9e8..2c9858cda6 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -3802,6 +3802,13 @@ rb_arithmetic_sequence_beg_len_step(VALUE obj, long *begp, long *lenp, long *ste https://github.com/ruby/ruby/blob/trunk/enumerator.c#L3802
     *stepp = step;
 
     if (step < 0) {
+        if (aseq.exclude_end && !NIL_P(aseq.end)) {
+            /* Handle exclusion before range reversal */
+            aseq.end = LONG2NUM(NUM2LONG(aseq.end) + 1);
+
+            /* Don't exclude the previous beginning */
+            aseq.exclude_end = 0;
+        }
         VALUE tmp = aseq.begin;
         aseq.begin = aseq.end;
         aseq.end = tmp;
diff --git a/ext/-test-/arith_seq/beg_len_step/beg_len_step.c b/ext/-test-/arith_seq/beg_len_step/beg_len_step.c
new file mode 100644
index 0000000000..40c8cbee82
--- /dev/null
+++ b/ext/-test-/arith_seq/beg_len_step/beg_len_step.c
@@ -0,0 +1,19 @@ https://github.com/ruby/ruby/blob/trunk/ext/-test-/arith_seq/beg_len_step/beg_len_step.c#L1
+#include "ruby/ruby.h"
+
+static VALUE
+arith_seq_s_beg_len_step(VALUE mod, VALUE obj, VALUE len, VALUE err)
+{
+  VALUE r;
+  long beg, len2, step;
+
+  r = rb_arithmetic_sequence_beg_len_step(obj, &beg, &len2, &step, NUM2LONG(len), NUM2INT(err));
+
+  return rb_ary_new_from_args(4, r, LONG2NUM(beg), LONG2NUM(len2), LONG2NUM(step));
+}
+
+void
+Init_beg_len_step(void)
+{
+    VALUE cArithSeq = rb_path2class("Enumerator::ArithmeticSequence");
+    rb_define_singleton_method(cArithSeq, "__beg_len_step__", arith_seq_s_beg_len_step, 3);
+}
diff --git a/ext/-test-/arith_seq/beg_len_step/depend b/ext/-test-/arith_seq/beg_len_step/depend
new file mode 100644
index 0000000000..36a2c4c71b
--- /dev/null
+++ b/ext/-test-/arith_seq/beg_len_step/depend
@@ -0,0 +1,161 @@ https://github.com/ruby/ruby/blob/trunk/ext/-test-/arith_seq/beg_len_step/depend#L1
+# AUTOGENERATED DEPENDENCIES START
+beg_len_step.o: $(RUBY_EXTCONF_H)
+beg_len_step.o: $(arch_hdrdir)/ruby/config.h
+beg_len_step.o: $(hdrdir)/ruby/assert.h
+beg_len_step.o: $(hdrdir)/ruby/backward.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/assume.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/attributes.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/bool.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/inttypes.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/limits.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/long_long.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/stdalign.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/stdarg.h
+beg_len_step.o: $(hdrdir)/ruby/defines.h
+beg_len_step.o: $(hdrdir)/ruby/intern.h
+beg_len_step.o: $(hdrdir)/ruby/internal/abi.h
+beg_len_step.o: $(hdrdir)/ruby/internal/anyargs.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/assume.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/artificial.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/cold.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/const.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/error.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/format.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/noalias.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/noinline.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/pure.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/restrict.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/warning.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/weakref.h
+beg_len_step.o: $(hdrdir)/ruby/internal/cast.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_since.h
+beg_len_step.o: $(hdrdir)/ruby/internal/config.h
+beg_len_step.o: $(hdrdir)/ruby/internal/constant_p.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rarray.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rbasic.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rbignum.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rclass.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rdata.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rfile.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rhash.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/robject.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rregexp.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rstring.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rstruct.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+beg_len_step.o: $(hdrdir)/ruby/internal/ctype.h
+beg_len_step.o: $(hdrdir)/ruby/internal/dllexport.h
+beg_len_step.o: $(hdrdir)/ruby/internal/dosish.h
+beg_len_step.o: $(hdrdir)/ruby/internal/error.h
+beg_len_step.o: $(hdrdir)/ruby/internal/eval.h
+beg_len_step.o: $(hdrdir)/ruby/internal/event.h
+beg_len_step.o: $(hdrdir)/ruby/internal/fl_type.h
+beg_len_step.o: $(hdrdir)/ruby/internal/gc.h
+beg_len_step.o: $(hdrdir)/ruby/internal/glob.h
+beg_len_step.o: $(hdrdir)/ruby/internal/globals.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/attribute.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/builtin.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/extension.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/feature.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/warning.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/array.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/bignum.h
+b (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]