From ebaa87f62692f4dfe5e209b3337d54ce147e8dcd Mon Sep 17 00:00:00 2001 From: yui-knk Date: Mon, 15 Apr 2024 21:26:38 +0900 Subject: [PATCH 01/39] Remove unused functions from `struct rb_parser_config_struct` --- node.c | 1 - ruby_parser.c | 17 ----------------- rubyparser.h | 5 ----- universal_parser.c | 5 ----- 4 files changed, 28 deletions(-) diff --git a/node.c b/node.c index 8a6b55b0b5808a..7706f71fdaeb44 100644 --- a/node.c +++ b/node.c @@ -81,7 +81,6 @@ rb_node_buffer_new(void) #define xfree ast->node_buffer->config->free #define rb_xmalloc_mul_add ast->node_buffer->config->xmalloc_mul_add #define ruby_xrealloc(var,size) (ast->node_buffer->config->realloc_n((void *)var, 1, size)) -#define rb_gc_mark_and_move ast->node_buffer->config->gc_mark_and_move #endif typedef void node_itr_t(rb_ast_t *ast, void *ctx, NODE *node); diff --git a/ruby_parser.c b/ruby_parser.c index 5d9c6c938f35db..16a868bc6b3707 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -309,18 +309,6 @@ syntax_error_new(void) return rb_class_new_instance(0, 0, rb_eSyntaxError); } -static VALUE -obj_write(VALUE old, VALUE *slot, VALUE young) -{ - return RB_OBJ_WRITE(old, slot, young); -} - -static VALUE -default_rs(void) -{ - return rb_default_rs; -} - static void * memmove2(void *dest, const void *src, size_t t, size_t n) { @@ -429,7 +417,6 @@ static const rb_parser_config_t rb_global_parser_config = { .ary_push = rb_ary_push, .ary_new_from_args = rb_ary_new_from_args, .ary_unshift = rb_ary_unshift, - .ary_modify = rb_ary_modify, .array_len = rb_array_len, .array_aref = RARRAY_AREF, @@ -476,7 +463,6 @@ static const rb_parser_config_t rb_global_parser_config = { .stderr_tty_p = rb_stderr_tty_p, .write_error_str = rb_write_error_str, - .default_rs = default_rs, .io_write = rb_io_write, .io_flush = rb_io_flush, .io_puts = rb_io_puts, @@ -501,7 +487,6 @@ static const rb_parser_config_t rb_global_parser_config = { .enc_mbcput = enc_mbcput, .enc_find_index = rb_enc_find_index, .enc_from_index = enc_from_index, - .enc_associate_index = rb_enc_associate_index, .enc_isspace = enc_isspace, .enc_coderange_7bit = ENC_CODERANGE_7BIT, .enc_coderange_unknown = ENC_CODERANGE_UNKNOWN, @@ -528,10 +513,8 @@ static const rb_parser_config_t rb_global_parser_config = { .sized_xfree = ruby_sized_xfree, .sized_realloc_n = ruby_sized_realloc_n, - .obj_write = obj_write, .gc_guard = gc_guard, .gc_mark = rb_gc_mark, - .gc_mark_and_move = rb_gc_mark_and_move, .reg_compile = rb_reg_compile, .reg_check_preprocess = rb_reg_check_preprocess, diff --git a/rubyparser.h b/rubyparser.h index d36e8dcede032f..6d346a7ff484a9 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -1264,7 +1264,6 @@ typedef struct rb_parser_config_struct { VALUE (*ary_push)(VALUE ary, VALUE elem); VALUE (*ary_new_from_args)(long n, ...); VALUE (*ary_unshift)(VALUE ary, VALUE item); - void (*ary_modify)(VALUE ary); long (*array_len)(VALUE a); VALUE (*array_aref)(VALUE, long); @@ -1318,7 +1317,6 @@ typedef struct rb_parser_config_struct { /* IO */ int (*stderr_tty_p)(void); void (*write_error_str)(VALUE mesg); - VALUE (*default_rs)(void); VALUE (*io_write)(VALUE io, VALUE str); VALUE (*io_flush)(VALUE io); VALUE (*io_puts)(int argc, const VALUE *argv, VALUE out); @@ -1345,7 +1343,6 @@ typedef struct rb_parser_config_struct { int (*enc_mbcput)(unsigned int c, void *buf, rb_encoding *enc); int (*enc_find_index)(const char *name); rb_encoding *(*enc_from_index)(int idx); - VALUE (*enc_associate_index)(VALUE obj, int encindex); int (*enc_isspace)(OnigCodePoint c, rb_encoding *enc); rb_encoding *(*enc_compatible)(VALUE str1, VALUE str2); VALUE (*enc_from_encoding)(rb_encoding *enc); @@ -1378,10 +1375,8 @@ typedef struct rb_parser_config_struct { /* GC */ void (*sized_xfree)(void *x, size_t size); void *(*sized_realloc_n)(void *ptr, size_t new_count, size_t element_size, size_t old_count); - VALUE (*obj_write)(VALUE, VALUE *, VALUE); void (*gc_guard)(VALUE); void (*gc_mark)(VALUE); - void (*gc_mark_and_move)(VALUE *ptr); /* Re */ VALUE (*reg_compile)(VALUE str, int options, const char *sourcefile, int sourceline); diff --git a/universal_parser.c b/universal_parser.c index 23a86311a5e039..2055681889ddb1 100644 --- a/universal_parser.c +++ b/universal_parser.c @@ -95,7 +95,6 @@ #undef rb_ary_new_from_args #define rb_ary_new_from_args p->config->ary_new_from_args #define rb_ary_unshift p->config->ary_unshift -#define rb_ary_modify p->config->ary_modify #undef RARRAY_LEN #define RARRAY_LEN p->config->array_len #define RARRAY_AREF p->config->array_aref @@ -154,7 +153,6 @@ #define rb_stderr_tty_p p->config->stderr_tty_p #define rb_write_error_str p->config->write_error_str -#define rb_default_rs p->config->default_rs() #define rb_io_write p->config->io_write #define rb_io_flush p->config->io_flush #define rb_io_puts p->config->io_puts @@ -179,7 +177,6 @@ #define rb_enc_mbcput p->config->enc_mbcput #define rb_enc_find_index p->config->enc_find_index #define rb_enc_from_index p->config->enc_from_index -#define rb_enc_associate_index p->config->enc_associate_index #define rb_enc_isspace p->config->enc_isspace #define ENC_CODERANGE_7BIT p->config->enc_coderange_7bit #define ENC_CODERANGE_UNKNOWN p->config->enc_coderange_unknown @@ -202,8 +199,6 @@ #define ruby_sized_xfree p->config->sized_xfree #define SIZED_REALLOC_N(v, T, m, n) ((v) = (T *)p->config->sized_realloc_n((void *)(v), (m), sizeof(T), (n))) -#undef RB_OBJ_WRITE -#define RB_OBJ_WRITE(old, slot, young) p->config->obj_write((VALUE)(old), (VALUE *)(slot), (VALUE)(young)) #undef RB_GC_GUARD #define RB_GC_GUARD p->config->gc_guard #define rb_gc_mark p->config->gc_mark From 0118f5425ebf3c189f9cce73587f6b49934c95f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:24:03 +0000 Subject: [PATCH 02/39] [rubygems/rubygems] Bump rb-sys Bumps [rb-sys](https://github.com/oxidize-rb/rb-sys) from 0.9.91 to 0.9.94. - [Release notes](https://github.com/oxidize-rb/rb-sys/releases) - [Commits](https://github.com/oxidize-rb/rb-sys/compare/v0.9.91...v0.9.94) --- updated-dependencies: - dependency-name: rb-sys dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] https://github.com/rubygems/rubygems/commit/ac952f030b --- .../rust_ruby_example/Cargo.lock | 8 ++++---- .../rust_ruby_example/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock index f96b1442936e2f..7e1617a663784b 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock @@ -145,18 +145,18 @@ dependencies = [ [[package]] name = "rb-sys" -version = "0.9.91" +version = "0.9.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81203e271055178603e243fee397f5f4aac125bcd20036279683fb1445a899" +checksum = "06dab8dbb0beb0a575a80c4b46355c8ace1f3dc5df60a3109758f205f1061366" dependencies = [ "rb-sys-build", ] [[package]] name = "rb-sys-build" -version = "0.9.91" +version = "0.9.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de9403a6aac834e7c9534575cb14188b6b5b99bafe475d18d838d44fbc27d31" +checksum = "164d44950a42f2ba2f94efdcb650e14764270f84d281352aebb261806da0b2ce" dependencies = [ "bindgen", "lazy_static", diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml index dca81463949243..a84cc8aabbf6ca 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -rb-sys = "0.9.91" +rb-sys = "0.9.94" From fc8099aea93cb5e09a6bb0bc7b75656207c73240 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:39:29 +0000 Subject: [PATCH 03/39] [rubygems/rubygems] Bump rb-sys Bumps [rb-sys](https://github.com/oxidize-rb/rb-sys) from 0.9.91 to 0.9.94. - [Release notes](https://github.com/oxidize-rb/rb-sys/releases) - [Commits](https://github.com/oxidize-rb/rb-sys/compare/v0.9.91...v0.9.94) --- updated-dependencies: - dependency-name: rb-sys dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] https://github.com/rubygems/rubygems/commit/04cf565ebe --- .../custom_name/ext/custom_name_lib/Cargo.lock | 8 ++++---- .../custom_name/ext/custom_name_lib/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock index 34db31f61c81f4..b9fed0e2b0b46c 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock @@ -152,18 +152,18 @@ dependencies = [ [[package]] name = "rb-sys" -version = "0.9.91" +version = "0.9.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81203e271055178603e243fee397f5f4aac125bcd20036279683fb1445a899" +checksum = "06dab8dbb0beb0a575a80c4b46355c8ace1f3dc5df60a3109758f205f1061366" dependencies = [ "rb-sys-build", ] [[package]] name = "rb-sys-build" -version = "0.9.91" +version = "0.9.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de9403a6aac834e7c9534575cb14188b6b5b99bafe475d18d838d44fbc27d31" +checksum = "164d44950a42f2ba2f94efdcb650e14764270f84d281352aebb261806da0b2ce" dependencies = [ "bindgen", "lazy_static", diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml index 00a48df5d57ddb..9f844b62be54dc 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -rb-sys = "0.9.91" +rb-sys = "0.9.94" From 4fcf007e851c68588fdf650459b606fce05c6a39 Mon Sep 17 00:00:00 2001 From: Kouhei Yanagita Date: Fri, 12 Apr 2024 15:18:10 +0900 Subject: [PATCH 04/39] [DOC] Update NEWS.md [Misc #18984] --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index 34fa51ce9d051a..a2612481f3b15f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -32,6 +32,10 @@ Note: We're only listing outstanding class updates. * Exception#set_backtrace now accepts arrays of `Thread::Backtrace::Location`. `Kernel#raise`, `Thread#raise` and `Fiber#raise` also accept this new format. [[Feature #13557]] +* Range + + * Range#size now raises TypeError if the range is not iterable. [[Misc #18984]] + ## Stdlib updates The following default gems are updated. @@ -123,6 +127,7 @@ See GitHub releases like [GitHub Releases of Logger](https://github.com/ruby/log [Feature #16495]: https://bugs.ruby-lang.org/issues/16495 [Feature #18290]: https://bugs.ruby-lang.org/issues/18290 [Feature #18980]: https://bugs.ruby-lang.org/issues/18980 +[Misc #18984]: https://bugs.ruby-lang.org/issues/18984 [Feature #19117]: https://bugs.ruby-lang.org/issues/19117 [Bug #19918]: https://bugs.ruby-lang.org/issues/19918 [Bug #20064]: https://bugs.ruby-lang.org/issues/20064 From c49742739e6764b008e262c497fd5e131090ed7a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 02:21:39 +0000 Subject: [PATCH 05/39] Bump github/codeql-action from 3.24.10 to 3.25.0 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.10 to 3.25.0. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4355270be187e1b672a7a1c7c7bae5afdc1ab94a...df5a14dc28094dc936e103b37d749c6628682b60) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 8 ++++---- .github/workflows/scorecards.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 38148d4f667ce6..f0dab96550c7ac 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -80,15 +80,15 @@ jobs: run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb - name: Initialize CodeQL - uses: github/codeql-action/init@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # v3.24.10 + uses: github/codeql-action/init@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # v3.24.10 + uses: github/codeql-action/autobuild@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # v3.24.10 + uses: github/codeql-action/analyze@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 with: category: '/language:${{ matrix.language }}' upload: False @@ -118,7 +118,7 @@ jobs: continue-on-error: true - name: Upload SARIF - uses: github/codeql-action/upload-sarif@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # v3.24.10 + uses: github/codeql-action/upload-sarif@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 with: sarif_file: sarif-results/${{ matrix.language }}.sarif continue-on-error: true diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 69b31e6b698783..99f85235ad6f04 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # v2.1.27 + uses: github/codeql-action/upload-sarif@df5a14dc28094dc936e103b37d749c6628682b60 # v2.1.27 with: sarif_file: results.sarif From f8f542bd9b5c15dd8d0f7facdfd33302c30d9c9b Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 22 Feb 2024 15:35:59 -0500 Subject: [PATCH 06/39] [ruby/pathname] Remove check for File.birthtime File.birthtime has existed since Ruby 2.2, and pathname requires Ruby >= 2.7.0, so the method will always be there. https://github.com/ruby/pathname/commit/aca9613bbf --- ext/pathname/extconf.rb | 1 - ext/pathname/pathname.c | 5 ----- 2 files changed, 6 deletions(-) diff --git a/ext/pathname/extconf.rb b/ext/pathname/extconf.rb index 84e68277aae84e..b4e1617b9e6b7f 100644 --- a/ext/pathname/extconf.rb +++ b/ext/pathname/extconf.rb @@ -1,4 +1,3 @@ # frozen_string_literal: false require 'mkmf' -have_func("rb_file_s_birthtime") create_makefile('pathname') diff --git a/ext/pathname/pathname.c b/ext/pathname/pathname.c index 878f216fb5cad7..cdecb3f897ee68 100644 --- a/ext/pathname/pathname.c +++ b/ext/pathname/pathname.c @@ -479,7 +479,6 @@ path_atime(VALUE self) return rb_funcall(rb_cFile, id_atime, 1, get_strpath(self)); } -#if defined(HAVE_RB_FILE_S_BIRTHTIME) /* * call-seq: * pathname.birthtime -> time @@ -494,10 +493,6 @@ path_birthtime(VALUE self) { return rb_funcall(rb_cFile, id_birthtime, 1, get_strpath(self)); } -#else -/* check at compilation time for `respond_to?` */ -# define path_birthtime rb_f_notimplement -#endif /* * call-seq: From 53a8ad151bf2a5a986f294027178659aad1a5bd5 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 16 Apr 2024 15:09:56 +0900 Subject: [PATCH 07/39] Escape colons in pre-commit dependency [ci skip] Colons are special in Makefiles. --- defs/gmake.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defs/gmake.mk b/defs/gmake.mk index 40a4750c733e5f..e502b9f83e19c3 100644 --- a/defs/gmake.mk +++ b/defs/gmake.mk @@ -193,7 +193,7 @@ $(SCRIPTBINDIR): $(Q) mkdir $@ .PHONY: commit -COMMIT_PREPARE := $(filter-out commit do-commit,$(MAKECMDGOALS)) up +COMMIT_PREPARE := $(subst :,\:,$(filter-out commit do-commit,$(MAKECMDGOALS))) up commit: pre-commit $(DOT_WAIT) do-commit $(DOT_WAIT) post_commit pre-commit: $(COMMIT_PREPARE) From 29110fe18d8f10f649cbcd43a9726069bfff1c54 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 16 Apr 2024 16:13:19 +0900 Subject: [PATCH 08/39] [Bug #20325] `Enumerator.product.size` is 0 if any size is 0 --- enumerator.c | 9 +++++++++ test/ruby/test_enumerator.rb | 17 ++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/enumerator.c b/enumerator.c index 989fdb34263d0f..193a865dbc5536 100644 --- a/enumerator.c +++ b/enumerator.c @@ -3536,10 +3536,19 @@ static VALUE enum_product_total_size(VALUE enums) { VALUE total = INT2FIX(1); + VALUE sizes = rb_ary_hidden_new(RARRAY_LEN(enums)); long i; for (i = 0; i < RARRAY_LEN(enums); i++) { VALUE size = enum_size(RARRAY_AREF(enums, i)); + if (size == INT2FIX(0)) { + rb_ary_resize(sizes, 0); + return size; + } + rb_ary_push(sizes, size); + } + for (i = 0; i < RARRAY_LEN(sizes); i++) { + VALUE size = RARRAY_AREF(sizes, i); if (NIL_P(size) || (RB_TYPE_P(size, T_FLOAT) && isinf(NUM2DBL(size)))) { return size; diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb index 825c191d874c81..7599d434635d19 100644 --- a/test/ruby/test_enumerator.rb +++ b/test/ruby/test_enumerator.rb @@ -953,11 +953,7 @@ def each(&block) assert_equal(true, e.is_lambda) end - def test_product - ## - ## Enumerator::Product - ## - + def test_product_new # 0-dimensional e = Enumerator::Product.new assert_instance_of(Enumerator::Product, e) @@ -994,15 +990,16 @@ def test_product e.each { |x,| heads << x } assert_equal [1, 1, 2, 2, 3, 3], heads + # Any enumerable is 0 size + assert_equal(0, Enumerator::Product.new([], 1..).size) + # Reject keyword arguments assert_raise(ArgumentError) { Enumerator::Product.new(1..3, foo: 1, bar: 2) } + end - ## - ## Enumerator.product - ## - + def test_s_product # without a block e = Enumerator.product(1..3, %w[a b]) assert_instance_of(Enumerator::Product, e) @@ -1029,6 +1026,8 @@ def test_product assert_equal(nil, e.size) assert_equal [[1, "a"], [1, "b"], [2, "a"], [2, "b"]], e.take(4) + assert_equal(0, Enumerator.product([], 1..).size) + # Reject keyword arguments assert_raise(ArgumentError) { Enumerator.product(1..3, foo: 1, bar: 2) From 54d472d91fe9fc724969a6ed71a3919710e28bfa Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 24 Jan 2021 18:17:28 +0900 Subject: [PATCH 09/39] [rubygems/rubygems] Honor a specified path as the temporary diretory if given ## The problem Currently the tests are executed in the fixed name directory "tmp" under the top source directory. However it makes the tests fail when the source path contains symlinks. Or unable to even start if the top source directory is read-only, e.g., remote-mounting in read-only mode from virtual machines. Also, with the fixed directory, there is no way to avoid `pend` in `TestGemPackage#test_extract_symlink_parent_doesnt_delete_user_dir`. ## The fix Instead of creating the fixed name directory, this PR allows to use a different path given with the environment variable "GEM_TEST_TMPDIR". The default path is, as well as the current behavior, "tmp" from the top source directory. ### Caveat It is the caller's responsibility to make the directory safe (owned, world unwritable, or sticky) when setting the environment variable. https://github.com/rubygems/rubygems/commit/bf00850656 --- test/rubygems/helper.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index 82fb50b70492c7..f97306717d1b47 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -285,9 +285,12 @@ def assert_contains_make_command(target, output, msg = nil) def setup @orig_hooks = {} @orig_env = ENV.to_hash - @tmp = File.expand_path("../../tmp", __dir__) - FileUtils.mkdir_p @tmp + top_srcdir = __dir__ + "/../.." + @tmp = File.expand_path(ENV.fetch("GEM_TEST_TMPDIR", "tmp"), top_srcdir) + + FileUtils.mkdir_p(@tmp, mode: 0o700) # =rwx + @tmp = File.realpath(@tmp) @tempdir = Dir.mktmpdir("test_rubygems_", @tmp) From 639449fe8d2493576faa764b1766ff2bc9c154ed Mon Sep 17 00:00:00 2001 From: Mari Imaizumi Date: Tue, 16 Apr 2024 20:58:46 +0900 Subject: [PATCH 10/39] [ruby/reline] Implement changing editing mode (https://github.com/ruby/reline/pull/681) https://github.com/ruby/reline/commit/501b9a6c5f --- lib/reline/line_editor.rb | 8 ++++++++ test/reline/test_key_actor_emacs.rb | 5 +++++ test/reline/test_key_actor_vi.rb | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index e4d7ecf1a29189..36bd6d435f46ef 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -2630,4 +2630,12 @@ def finish @mark_pointer = new_pointer end alias_method :exchange_point_and_mark, :em_exchange_mark + + private def emacs_editing_mode(key) + @config.editing_mode = :emacs + end + + private def vi_editing_mode(key) + @config.editing_mode = :vi_insert + end end diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb index 8f5676a1d4f170..a9baf9ad3724a6 100644 --- a/test/reline/test_key_actor_emacs.rb +++ b/test/reline/test_key_actor_emacs.rb @@ -1436,4 +1436,9 @@ def test_unix_line_discard input_keys("\C-f\C-u", false) assert_line_around_cursor('', '') end + + def test_vi_editing_mode + @line_editor.__send__(:vi_editing_mode, nil) + assert(@config.editing_mode_is?(:vi_insert)) + end end diff --git a/test/reline/test_key_actor_vi.rb b/test/reline/test_key_actor_vi.rb index cf3943ae379bce..4deae2dd8313c1 100644 --- a/test/reline/test_key_actor_vi.rb +++ b/test/reline/test_key_actor_vi.rb @@ -911,4 +911,9 @@ def test_vi_motion_operators input_keys("test = { foo: bar }\C-[BBBldt}b") end end + + def test_emacs_editing_mode + @line_editor.__send__(:emacs_editing_mode, nil) + assert(@config.editing_mode_is?(:emacs)) + end end From 8e341d81c9a5d9874c2d4b65d873425ff94bc3b7 Mon Sep 17 00:00:00 2001 From: Mari Imaizumi Date: Tue, 16 Apr 2024 21:42:53 +0900 Subject: [PATCH 11/39] [ruby/reline] Bump version to 0.5.2 (https://github.com/ruby/reline/pull/682) https://github.com/ruby/reline/commit/17d12cc511 --- lib/reline/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/reline/version.rb b/lib/reline/version.rb index acb5e279b8cc77..e6f370c6ec1438 100644 --- a/lib/reline/version.rb +++ b/lib/reline/version.rb @@ -1,3 +1,3 @@ module Reline - VERSION = '0.5.1' + VERSION = '0.5.2' end From e8f3ea3f8764fe0978d3c6d330818bc8d5467f87 Mon Sep 17 00:00:00 2001 From: git Date: Tue, 16 Apr 2024 12:44:04 +0000 Subject: [PATCH 12/39] Update default gems list at 8e341d81c9a5d9874c2d4b65d87342 [ci skip] --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index a2612481f3b15f..98e4f17cf7a3a4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -51,7 +51,7 @@ The following default gems are updated. * optparse 0.5.0 * prism 0.25.0 * rdoc 6.6.3.1 -* reline 0.5.1 +* reline 0.5.2 * resolv 0.4.0 * stringio 3.1.1 * strscan 3.1.1 From 982dfa07936001013aafedd8aa656c69e268ebc3 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 12 Apr 2024 20:16:07 -0400 Subject: [PATCH 13/39] [ruby/prism] Better error recovery for unwritable nodes https://github.com/ruby/prism/commit/4828e73263 --- prism/config.yml | 8 +++++ prism/prism.c | 48 +++++++++++++++++++++++++--- prism/templates/src/diagnostic.c.erb | 8 +++++ 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index a0abb98ef7e3a8..8551c95b1f6c23 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -104,6 +104,14 @@ errors: - EXPECT_STRING_CONTENT - EXPECT_WHEN_DELIMITER - EXPRESSION_BARE_HASH + - EXPRESSION_NOT_WRITABLE + - EXPRESSION_NOT_WRITABLE_ENCODING + - EXPRESSION_NOT_WRITABLE_FALSE + - EXPRESSION_NOT_WRITABLE_FILE + - EXPRESSION_NOT_WRITABLE_LINE + - EXPRESSION_NOT_WRITABLE_NIL + - EXPRESSION_NOT_WRITABLE_SELF + - EXPRESSION_NOT_WRITABLE_TRUE - FLOAT_PARSE - FOR_COLLECTION - FOR_IN diff --git a/prism/prism.c b/prism/prism.c index 91d27f566d4e00..695734d0a39e7e 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -12945,6 +12945,32 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod } } +/** + * Certain expressions are not writable, but in order to provide a better + * experience we give a specific error message. In order to maintain as much + * information in the tree as possible, we replace them with local variable + * writes. + */ +static pm_node_t * +parse_unwriteable_write(pm_parser_t *parser, pm_node_t *target, const pm_token_t *equals, pm_node_t *value) { + switch (PM_NODE_TYPE(target)) { + case PM_SOURCE_ENCODING_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_ENCODING); break; + case PM_FALSE_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_FALSE); break; + case PM_SOURCE_FILE_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_FILE); break; + case PM_SOURCE_LINE_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_LINE); break; + case PM_NIL_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_NIL); break; + case PM_SELF_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_SELF); break; + case PM_TRUE_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_TRUE); break; + default: break; + } + + pm_constant_id_t name = pm_parser_constant_id_location(parser, target->location.start, target->location.end); + pm_local_variable_write_node_t *result = pm_local_variable_write_node_create(parser, name, 0, value, &target->location, equals); + + pm_node_destroy(parser, target); + return (pm_node_t *) result; +} + /** * Parse a list of targets for assignment. This is used in the case of a for * loop or a multi-assignment. For example, in the following code: @@ -19357,13 +19383,25 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL); return parse_write(parser, (pm_node_t *) multi_target, &token, value); } + case PM_SOURCE_ENCODING_NODE: + case PM_FALSE_NODE: + case PM_SOURCE_FILE_NODE: + case PM_SOURCE_LINE_NODE: + case PM_NIL_NODE: + case PM_SELF_NODE: + case PM_TRUE_NODE: { + // In these special cases, we have specific error messages + // and we will replace them with local variable writes. + parser_lex(parser); + pm_node_t *value = parse_assignment_values(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL); + return parse_unwriteable_write(parser, node, &token, value); + } default: + // In this case we have an = sign, but we don't know what + // it's for. We need to treat it as an error. We'll mark it + // as an error and skip past it. parser_lex(parser); - - // In this case we have an = sign, but we don't know what it's for. We - // need to treat it as an error. For now, we'll mark it as an error - // and just skip right past it. - pm_parser_err_token(parser, &token, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL); + pm_parser_err_token(parser, &token, PM_ERR_EXPRESSION_NOT_WRITABLE); return node; } } diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 97ad451890a2a2..42f802455146ea 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -188,6 +188,14 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_EXPECT_STRING_CONTENT] = { "expected string content after opening string delimiter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_WHEN_DELIMITER] = { "expected a delimiter after the predicates of a `when` clause", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPRESSION_BARE_HASH] = { "unexpected bare hash in expression", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPRESSION_NOT_WRITABLE] = { "unexpected '='; target cannot be written", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPRESSION_NOT_WRITABLE_ENCODING] = { "Can't assign to __ENCODING__", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPRESSION_NOT_WRITABLE_FALSE] = { "Can't assign to false", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPRESSION_NOT_WRITABLE_FILE] = { "Can't assign to __FILE__", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPRESSION_NOT_WRITABLE_LINE] = { "Can't assign to __LINE__", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPRESSION_NOT_WRITABLE_NIL] = { "Can't assign to nil", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPRESSION_NOT_WRITABLE_SELF] = { "Can't change the value of self", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPRESSION_NOT_WRITABLE_TRUE] = { "Can't assign to true", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_FLOAT_PARSE] = { "could not parse the float '%.*s'", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_FOR_COLLECTION] = { "expected a collection after the `in` in a `for` statement", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_FOR_INDEX] = { "expected an index after `for`", PM_ERROR_LEVEL_SYNTAX }, From 79df0f135e9179b64f6fa29d5131f586511a088b Mon Sep 17 00:00:00 2001 From: tomoya ishida Date: Tue, 16 Apr 2024 23:06:18 +0900 Subject: [PATCH 14/39] [ruby/reline] Refactor history move and history search (https://github.com/ruby/reline/pull/651) https://github.com/ruby/reline/commit/90e43e01d4 --- lib/reline/line_editor.rb | 399 +++++++++++++------------------------- 1 file changed, 134 insertions(+), 265 deletions(-) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 36bd6d435f46ef..c84a78a06cc94f 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -1543,118 +1543,89 @@ def finish end alias_method :end_of_line, :ed_move_to_end - private def generate_searcher - Fiber.new do |first_key| - prev_search_key = first_key - search_word = String.new(encoding: @encoding) - multibyte_buf = String.new(encoding: 'ASCII-8BIT') - last_hit = nil - case first_key - when "\C-r".ord - prompt_name = 'reverse-i-search' - when "\C-s".ord - prompt_name = 'i-search' + private def generate_searcher(search_key) + search_word = String.new(encoding: @encoding) + multibyte_buf = String.new(encoding: 'ASCII-8BIT') + last_hit = nil + hit_pointer = nil + lambda do |key| + search_again = false + case key + when "\C-h".ord, "\C-?".ord + grapheme_clusters = search_word.grapheme_clusters + if grapheme_clusters.size > 0 + grapheme_clusters.pop + search_word = grapheme_clusters.join + end + when "\C-r".ord, "\C-s".ord + search_again = true if search_key == key + search_key = key + else + multibyte_buf << key + if multibyte_buf.dup.force_encoding(@encoding).valid_encoding? + search_word << multibyte_buf.dup.force_encoding(@encoding) + multibyte_buf.clear + end end - loop do - key = Fiber.yield(search_word) - search_again = false - case key - when -1 # determined - Reline.last_incremental_search = search_word - break - when "\C-h".ord, "\C-?".ord - grapheme_clusters = search_word.grapheme_clusters - if grapheme_clusters.size > 0 - grapheme_clusters.pop - search_word = grapheme_clusters.join - end - when "\C-r".ord, "\C-s".ord - search_again = true if prev_search_key == key - prev_search_key = key - else - multibyte_buf << key - if multibyte_buf.dup.force_encoding(@encoding).valid_encoding? - search_word << multibyte_buf.dup.force_encoding(@encoding) - multibyte_buf.clear + hit = nil + if not search_word.empty? and @line_backup_in_history&.include?(search_word) + hit_pointer = Reline::HISTORY.size + hit = @line_backup_in_history + else + if search_again + if search_word.empty? and Reline.last_incremental_search + search_word = Reline.last_incremental_search end - end - hit = nil - if not search_word.empty? and @line_backup_in_history&.include?(search_word) - @history_pointer = nil - hit = @line_backup_in_history - else - if search_again - if search_word.empty? and Reline.last_incremental_search - search_word = Reline.last_incremental_search - end - if @history_pointer - case prev_search_key - when "\C-r".ord - history_pointer_base = 0 - history = Reline::HISTORY[0..(@history_pointer - 1)] - when "\C-s".ord - history_pointer_base = @history_pointer + 1 - history = Reline::HISTORY[(@history_pointer + 1)..-1] - end - else - history_pointer_base = 0 - history = Reline::HISTORY - end - elsif @history_pointer - case prev_search_key + if @history_pointer + case search_key when "\C-r".ord history_pointer_base = 0 - history = Reline::HISTORY[0..@history_pointer] + history = Reline::HISTORY[0..(@history_pointer - 1)] when "\C-s".ord - history_pointer_base = @history_pointer - history = Reline::HISTORY[@history_pointer..-1] + history_pointer_base = @history_pointer + 1 + history = Reline::HISTORY[(@history_pointer + 1)..-1] end else history_pointer_base = 0 history = Reline::HISTORY end - case prev_search_key + elsif @history_pointer + case search_key when "\C-r".ord - hit_index = history.rindex { |item| - item.include?(search_word) - } + history_pointer_base = 0 + history = Reline::HISTORY[0..@history_pointer] when "\C-s".ord - hit_index = history.index { |item| - item.include?(search_word) - } - end - if hit_index - @history_pointer = history_pointer_base + hit_index - hit = Reline::HISTORY[@history_pointer] + history_pointer_base = @history_pointer + history = Reline::HISTORY[@history_pointer..-1] end + else + history_pointer_base = 0 + history = Reline::HISTORY end - case prev_search_key + case search_key when "\C-r".ord - prompt_name = 'reverse-i-search' + hit_index = history.rindex { |item| + item.include?(search_word) + } when "\C-s".ord - prompt_name = 'i-search' + hit_index = history.index { |item| + item.include?(search_word) + } end - if hit - if @is_multiline - @buffer_of_lines = hit.split("\n") - @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? - @line_index = @buffer_of_lines.size - 1 - @byte_pointer = current_line.bytesize - @searching_prompt = "(%s)`%s'" % [prompt_name, search_word] - else - @buffer_of_lines = [hit] - @byte_pointer = hit.bytesize - @searching_prompt = "(%s)`%s': %s" % [prompt_name, search_word, hit] - end - last_hit = hit - else - if @is_multiline - @searching_prompt = "(failed %s)`%s'" % [prompt_name, search_word] - else - @searching_prompt = "(failed %s)`%s': %s" % [prompt_name, search_word, last_hit] - end + if hit_index + hit_pointer = history_pointer_base + hit_index + hit = Reline::HISTORY[hit_pointer] end end + case search_key + when "\C-r".ord + prompt_name = 'reverse-i-search' + when "\C-s".ord + prompt_name = 'i-search' + end + prompt_name = "failed #{prompt_name}" unless hit + last_hit = hit if hit_pointer + [search_word, prompt_name, hit_pointer, hit, last_hit] end end @@ -1666,8 +1637,7 @@ def finish @line_backup_in_history = current_line end end - searcher = generate_searcher - searcher.resume(key) + searcher = generate_searcher(key) @searching_prompt = "(reverse-i-search)`': " termination_keys = ["\C-j".ord] termination_keys.concat(@config.isearch_terminators&.chars&.map(&:ord)) if @config.isearch_terminators @@ -1689,7 +1659,6 @@ def finish @searching_prompt = nil @waiting_proc = nil @byte_pointer = 0 - searcher.resume(-1) when "\C-g".ord if @is_multiline @buffer_of_lines = @line_backup_in_history.split("\n") @@ -1698,15 +1667,21 @@ def finish else @buffer_of_lines = [@line_backup_in_history] end - @history_pointer = nil + move_history(nil, line: :end, cursor: :end, save_buffer: false) @searching_prompt = nil @waiting_proc = nil - @line_backup_in_history = nil @byte_pointer = 0 else chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT) if chr.match?(/[[:print:]]/) or k == "\C-h".ord or k == "\C-?".ord or k == "\C-r".ord or k == "\C-s".ord - searcher.resume(k) + search_word, prompt_name, hit_pointer, hit, last_hit = searcher.call(k) + Reline.last_incremental_search = search_word + if @is_multiline + @searching_prompt = "(%s)`%s'" % [prompt_name, search_word] + else + @searching_prompt = "(%s)`%s': %s" % [prompt_name, search_word, hit || last_hit] + end + move_history(hit_pointer, line: :end, cursor: :end, save_buffer: false) if hit_pointer else if @history_pointer line = Reline::HISTORY[@history_pointer] @@ -1725,7 +1700,6 @@ def finish @searching_prompt = nil @waiting_proc = nil @byte_pointer = 0 - searcher.resume(-1) end end } @@ -1741,104 +1715,70 @@ def finish end alias_method :forward_search_history, :vi_search_next - private def ed_search_prev_history(key, arg: 1) - history = nil - h_pointer = nil - line_no = nil - substr = current_line.slice(0, @byte_pointer) - if @history_pointer.nil? - return if not current_line.empty? and substr.empty? - history = Reline::HISTORY - elsif @history_pointer.zero? - history = nil - h_pointer = nil - else - history = Reline::HISTORY.slice(0, @history_pointer) - end - return if history.nil? - if @is_multiline - h_pointer = history.rindex { |h| - h.split("\n").each_with_index { |l, i| - if l.start_with?(substr) - line_no = i - break - end - } - not line_no.nil? - } - else - h_pointer = history.rindex { |l| - l.start_with?(substr) - } - end - return if h_pointer.nil? - @history_pointer = h_pointer - cursor = current_byte_pointer_cursor - if @is_multiline - @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n") - @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? - @line_index = line_no - calculate_nearest_cursor(cursor) - else - @buffer_of_lines = [Reline::HISTORY[@history_pointer]] - calculate_nearest_cursor(cursor) + private def search_history(prefix, pointer_range) + pointer_range.each do |pointer| + lines = Reline::HISTORY[pointer].split("\n") + lines.each_with_index do |line, index| + return [pointer, index] if line.start_with?(prefix) + end end + nil + end + + private def ed_search_prev_history(key, arg: 1) + substr = current_line.byteslice(0, @byte_pointer) + return if @history_pointer == 0 + return if @history_pointer.nil? && substr.empty? && !current_line.empty? + + history_range = 0...(@history_pointer || Reline::HISTORY.size) + h_pointer, line_index = search_history(substr, history_range.reverse_each) + return unless h_pointer + move_history(h_pointer, line: line_index || :start, cursor: @byte_pointer) arg -= 1 ed_search_prev_history(key, arg: arg) if arg > 0 end alias_method :history_search_backward, :ed_search_prev_history private def ed_search_next_history(key, arg: 1) - substr = current_line.slice(0, @byte_pointer) - if @history_pointer.nil? - return - elsif @history_pointer == (Reline::HISTORY.size - 1) and not substr.empty? - return - end + substr = current_line.byteslice(0, @byte_pointer) + return if @history_pointer.nil? + + history_range = @history_pointer + 1...Reline::HISTORY.size history = Reline::HISTORY.slice((@history_pointer + 1)..-1) - h_pointer = nil - line_no = nil - if @is_multiline - h_pointer = history.index { |h| - h.split("\n").each_with_index { |l, i| - if l.start_with?(substr) - line_no = i - break - end - } - not line_no.nil? - } + h_pointer, line_index = search_history(substr, history_range) + return if h_pointer.nil? and not substr.empty? + + move_history(h_pointer, line: line_index || :start, cursor: @byte_pointer) + arg -= 1 + ed_search_next_history(key, arg: arg) if arg > 0 + end + alias_method :history_search_forward, :ed_search_next_history + + private def move_history(history_pointer, line:, cursor:, save_buffer: true) + history_pointer ||= Reline::HISTORY.size + return if history_pointer < 0 || history_pointer > Reline::HISTORY.size + old_history_pointer = @history_pointer || Reline::HISTORY.size + if old_history_pointer == Reline::HISTORY.size + @line_backup_in_history = save_buffer ? whole_buffer : '' else - h_pointer = history.index { |l| - l.start_with?(substr) - } + Reline::HISTORY[old_history_pointer] = whole_buffer if save_buffer + end + if history_pointer == Reline::HISTORY.size + buf = @line_backup_in_history + @history_pointer = @line_backup_in_history = nil + else + buf = Reline::HISTORY[history_pointer] + @history_pointer = history_pointer end - h_pointer += @history_pointer + 1 if h_pointer and @history_pointer - return if h_pointer.nil? and not substr.empty? - @history_pointer = h_pointer if @is_multiline - if @history_pointer.nil? and substr.empty? - @buffer_of_lines = [] - @line_index = 0 - @byte_pointer = 0 - else - cursor = current_byte_pointer_cursor - @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n") - @line_index = line_no - calculate_nearest_cursor(cursor) - end + @buffer_of_lines = buf.split("\n") @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? + @line_index = line == :start ? 0 : line == :end ? @buffer_of_lines.size - 1 : line else - if @history_pointer.nil? and substr.empty? - set_current_line('', 0) - else - set_current_line(Reline::HISTORY[@history_pointer]) - end + @buffer_of_lines = [buf] end - arg -= 1 - ed_search_next_history(key, arg: arg) if arg > 0 + @byte_pointer = cursor == :start ? 0 : cursor == :end ? current_line.bytesize : cursor end - alias_method :history_search_forward, :ed_search_next_history private def ed_prev_history(key, arg: 1) if @is_multiline and @line_index > 0 @@ -1847,43 +1787,11 @@ def finish calculate_nearest_cursor(cursor) return end - if Reline::HISTORY.empty? - return - end - if @history_pointer.nil? - @history_pointer = Reline::HISTORY.size - 1 - cursor = current_byte_pointer_cursor - if @is_multiline - @line_backup_in_history = whole_buffer - @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n") - @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? - @line_index = @buffer_of_lines.size - 1 - calculate_nearest_cursor(cursor) - else - @line_backup_in_history = whole_buffer - @buffer_of_lines = [Reline::HISTORY[@history_pointer]] - calculate_nearest_cursor(cursor) - end - elsif @history_pointer.zero? - return - else - if @is_multiline - Reline::HISTORY[@history_pointer] = whole_buffer - @history_pointer -= 1 - @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n") - @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? - @line_index = @buffer_of_lines.size - 1 - else - Reline::HISTORY[@history_pointer] = whole_buffer - @history_pointer -= 1 - @buffer_of_lines = [Reline::HISTORY[@history_pointer]] - end - end - if @config.editing_mode_is?(:emacs, :vi_insert) - @byte_pointer = current_line.bytesize - elsif @config.editing_mode_is?(:vi_command) - @byte_pointer = 0 - end + move_history( + (@history_pointer || Reline::HISTORY.size) - 1, + line: :end, + cursor: @config.editing_mode_is?(:vi_command) ? :start : :end, + ) arg -= 1 ed_prev_history(key, arg: arg) if arg > 0 end @@ -1896,36 +1804,11 @@ def finish calculate_nearest_cursor(cursor) return end - if @history_pointer.nil? - return - elsif @history_pointer == (Reline::HISTORY.size - 1) - if @is_multiline - @history_pointer = nil - @buffer_of_lines = @line_backup_in_history.split("\n") - @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? - @line_index = 0 - else - @history_pointer = nil - @buffer_of_lines = [@line_backup_in_history] - end - else - if @is_multiline - Reline::HISTORY[@history_pointer] = whole_buffer - @history_pointer += 1 - @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n") - @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? - @line_index = 0 - else - Reline::HISTORY[@history_pointer] = whole_buffer - @history_pointer += 1 - @buffer_of_lines = [Reline::HISTORY[@history_pointer]] - end - end - if @config.editing_mode_is?(:emacs, :vi_insert) - @byte_pointer = current_line.bytesize - elsif @config.editing_mode_is?(:vi_command) - @byte_pointer = 0 - end + move_history( + (@history_pointer || Reline::HISTORY.size) + 1, + line: :start, + cursor: @config.editing_mode_is?(:vi_command) ? :start : :end, + ) arg -= 1 ed_next_history(key, arg: arg) if arg > 0 end @@ -1956,10 +1839,6 @@ def finish end end else - if @history_pointer - Reline::HISTORY[@history_pointer] = whole_buffer - @history_pointer = nil - end finish end end @@ -2409,17 +2288,7 @@ def finish if Reline::HISTORY.empty? return end - if @history_pointer.nil? - @history_pointer = 0 - @line_backup_in_history = current_line - set_current_line(Reline::HISTORY[@history_pointer], 0) - elsif @history_pointer.zero? - return - else - Reline::HISTORY[@history_pointer] = current_line - @history_pointer = 0 - set_current_line(Reline::HISTORY[@history_pointer], 0) - end + move_history(0, line: :start, cursor: :start) end private def vi_histedit(key) From 646a00892e80a106c1166ea529b18b780982942d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 16 Apr 2024 10:20:59 -0400 Subject: [PATCH 15/39] [ruby/prism] Fix up clang-analyzer violations https://github.com/ruby/prism/commit/259aef2acd --- prism/prism.c | 3 +++ prism/util/pm_integer.c | 18 ++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 695734d0a39e7e..9c489e478567bf 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -2774,6 +2774,7 @@ pm_call_node_not_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t *me if (arguments->closing_loc.start != NULL) { node->base.location.end = arguments->closing_loc.end; } else { + assert(receiver != NULL); node->base.location.end = receiver->location.end; } @@ -21229,6 +21230,8 @@ pm_parser_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, if (inline_messages) { pm_buffer_append_byte(buffer, ' '); + assert(error->error != NULL); + const char *message = error->error->message; pm_buffer_append_string(buffer, message, strlen(message)); } diff --git a/prism/util/pm_integer.c b/prism/util/pm_integer.c index 8f8b75474df33a..50210f0cb1cac6 100644 --- a/prism/util/pm_integer.c +++ b/prism/util/pm_integer.c @@ -172,21 +172,21 @@ karatsuba_multiply(pm_integer_t *destination, pm_integer_t *left, pm_integer_t * pm_integer_t y0 = { 0, half, right_values, false }; pm_integer_t y1 = { 0, right_length - half, right_values + half, false }; - pm_integer_t z0; + pm_integer_t z0 = { 0 }; karatsuba_multiply(&z0, &x0, &y0, base); - pm_integer_t z2; + pm_integer_t z2 = { 0 }; karatsuba_multiply(&z2, &x1, &y1, base); // For simplicity to avoid considering negative values, // use `z1 = (x0 + x1) * (y0 + y1) - z0 - z2` instead of original karatsuba algorithm. - pm_integer_t x01; + pm_integer_t x01 = { 0 }; big_add(&x01, &x0, &x1, base); - pm_integer_t y01; + pm_integer_t y01 = { 0 }; big_add(&y01, &y0, &y1, base); - pm_integer_t xy; + pm_integer_t xy = { 0 }; karatsuba_multiply(&xy, &x01, &y01, base); pm_integer_t z1; @@ -326,6 +326,8 @@ pm_integer_convert_base(pm_integer_t *destination, const pm_integer_t *source, u INTEGER_EXTRACT(source, source_length, source_values) size_t bigints_length = (source_length + 1) / 2; + assert(bigints_length > 0); + pm_integer_t *bigints = (pm_integer_t *) xcalloc(bigints_length, sizeof(pm_integer_t)); if (bigints == NULL) return; @@ -345,13 +347,13 @@ pm_integer_convert_base(pm_integer_t *destination, const pm_integer_t *source, u base = next_base; size_t next_length = (bigints_length + 1) / 2; - pm_integer_t *next_bigints = (pm_integer_t *) xmalloc(sizeof(pm_integer_t) * next_length); + pm_integer_t *next_bigints = (pm_integer_t *) xcalloc(next_length, sizeof(pm_integer_t)); for (size_t bigints_index = 0; bigints_index < bigints_length; bigints_index += 2) { if (bigints_index + 1 == bigints_length) { next_bigints[bigints_index / 2] = bigints[bigints_index]; } else { - pm_integer_t multiplied; + pm_integer_t multiplied = { 0 }; karatsuba_multiply(&multiplied, &base, &bigints[bigints_index + 1], base_to); big_add(&next_bigints[bigints_index / 2], &bigints[bigints_index], &multiplied, base_to); @@ -584,7 +586,7 @@ pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer) { } // Otherwise, first we'll convert the base from 1<<32 to 10**9. - pm_integer_t converted; + pm_integer_t converted = { 0 }; pm_integer_convert_base(&converted, integer, (uint64_t) 1 << 32, 1000000000); if (converted.values == NULL) { From 39b13e581835d29f03da08c5df1a6f5d8d5a7957 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 16 Apr 2024 07:41:21 -0700 Subject: [PATCH 16/39] YJIT: End send fallback blocks (#10539) --- yjit/src/codegen.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index d60f4f0ec1029b..8ab5e0e230858d 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -8223,6 +8223,7 @@ fn gen_struct_aset( fn gen_send_dynamic Opnd>( jit: &mut JITState, asm: &mut Assembler, + ocb: &mut OutlinedCb, cd: *const rb_call_data, sp_pops: usize, vm_sendish: F, @@ -8262,7 +8263,10 @@ fn gen_send_dynamic Opnd>( gen_counter_incr(asm, Counter::num_send_dynamic); jit_perf_symbol_pop!(jit, asm, PerfMap::Codegen); - Some(KeepCompiling) + + // End the current block for invalidationg and sharing the same successor + jump_to_next_insn(jit, asm, ocb); + Some(EndBlock) } fn gen_send_general( @@ -8776,7 +8780,7 @@ fn gen_opt_send_without_block( } // Otherwise, fallback to dynamic dispatch using the interpreter's implementation of send - gen_send_dynamic(jit, asm, cd, unsafe { rb_yjit_sendish_sp_pops((*cd).ci) }, |asm| { + gen_send_dynamic(jit, asm, ocb, cd, unsafe { rb_yjit_sendish_sp_pops((*cd).ci) }, |asm| { extern "C" { fn rb_vm_opt_send_without_block(ec: EcPtr, cfp: CfpPtr, cd: VALUE) -> VALUE; } @@ -8801,7 +8805,7 @@ fn gen_send( // Otherwise, fallback to dynamic dispatch using the interpreter's implementation of send let blockiseq = jit.get_arg(1).as_iseq(); - gen_send_dynamic(jit, asm, cd, unsafe { rb_yjit_sendish_sp_pops((*cd).ci) }, |asm| { + gen_send_dynamic(jit, asm, ocb, cd, unsafe { rb_yjit_sendish_sp_pops((*cd).ci) }, |asm| { extern "C" { fn rb_vm_send(ec: EcPtr, cfp: CfpPtr, cd: VALUE, blockiseq: IseqPtr) -> VALUE; } @@ -8824,7 +8828,7 @@ fn gen_invokeblock( } // Otherwise, fallback to dynamic dispatch using the interpreter's implementation of send - gen_send_dynamic(jit, asm, cd, unsafe { rb_yjit_invokeblock_sp_pops((*cd).ci) }, |asm| { + gen_send_dynamic(jit, asm, ocb, cd, unsafe { rb_yjit_invokeblock_sp_pops((*cd).ci) }, |asm| { extern "C" { fn rb_vm_invokeblock(ec: EcPtr, cfp: CfpPtr, cd: VALUE) -> VALUE; } @@ -8984,7 +8988,7 @@ fn gen_invokesuper( // Otherwise, fallback to dynamic dispatch using the interpreter's implementation of send let blockiseq = jit.get_arg(1).as_iseq(); - gen_send_dynamic(jit, asm, cd, unsafe { rb_yjit_sendish_sp_pops((*cd).ci) }, |asm| { + gen_send_dynamic(jit, asm, ocb, cd, unsafe { rb_yjit_sendish_sp_pops((*cd).ci) }, |asm| { extern "C" { fn rb_vm_invokesuper(ec: EcPtr, cfp: CfpPtr, cd: VALUE, blockiseq: IseqPtr) -> VALUE; } From 7380e3d30ff3d33fa7dd3756929e5718be665bba Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Tue, 16 Apr 2024 14:23:45 +0200 Subject: [PATCH 17/39] RB_OBJ_FREEZE_RAW: Set the object shape --- include/ruby/internal/fl_type.h | 13 +++++-------- variable.c | 5 ++++- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/ruby/internal/fl_type.h b/include/ruby/internal/fl_type.h index eb212db7dc9555..0a05166784b4e0 100644 --- a/include/ruby/internal/fl_type.h +++ b/include/ruby/internal/fl_type.h @@ -905,6 +905,10 @@ RB_OBJ_FROZEN(VALUE obj) } } +RUBY_SYMBOL_EXPORT_BEGIN +void rb_obj_freeze_inline(VALUE obj); +RUBY_SYMBOL_EXPORT_END + RBIMPL_ATTR_ARTIFICIAL() /** * This is an implementation detail of RB_OBJ_FREEZE(). 3rd parties need not @@ -915,14 +919,7 @@ RBIMPL_ATTR_ARTIFICIAL() static inline void RB_OBJ_FREEZE_RAW(VALUE obj) { - RB_FL_SET_RAW(obj, RUBY_FL_FREEZE); - if (TYPE(obj) == T_STRING) { - RB_FL_UNSET_RAW(obj, FL_USER3); // STR_CHILLED - } + rb_obj_freeze_inline(obj); } -RUBY_SYMBOL_EXPORT_BEGIN -void rb_obj_freeze_inline(VALUE obj); -RUBY_SYMBOL_EXPORT_END - #endif /* RBIMPL_FL_TYPE_H */ diff --git a/variable.c b/variable.c index 807f01d64f821a..fcde8a603e3621 100644 --- a/variable.c +++ b/variable.c @@ -1815,7 +1815,10 @@ rb_shape_set_shape_id(VALUE obj, shape_id_t shape_id) void rb_obj_freeze_inline(VALUE x) { if (RB_FL_ABLE(x)) { - RB_OBJ_FREEZE_RAW(x); + RB_FL_SET_RAW(x, RUBY_FL_FREEZE); + if (TYPE(x) == T_STRING) { + RB_FL_UNSET_RAW(x, FL_USER3); // STR_CHILLED + } rb_shape_t * next_shape = rb_shape_transition_shape_frozen(x); From f06670c5a2a1daa6595018858d5cfa429a8aeae6 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Tue, 16 Apr 2024 15:30:00 +0200 Subject: [PATCH 18/39] Eliminate usage of OBJ_FREEZE_RAW Previously it would bypass the `FL_ABLE` check, but since shapes introduction, it started having a different behavior than `OBJ_FREEZE`, as it would onyl set the `FL_FREEZE` flag, but not update the shape. I have no indication of this causing a bug yet, but it seems like a trap waiting to happen. --- class.c | 2 +- compile.c | 2 +- complex.c | 4 ++-- rational.c | 4 ++-- ruby.c | 6 +++--- string.c | 6 +++--- struct.c | 14 +++++++------- thread.c | 4 ++-- vm_args.c | 2 +- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/class.c b/class.c index 879c0ead2af2ed..5cce99e334d8b1 100644 --- a/class.c +++ b/class.c @@ -2273,7 +2273,7 @@ rb_freeze_singleton_class(VALUE x) VALUE klass = RBASIC_CLASS(x); if (klass && // no class when hidden from ObjectSpace FL_TEST(klass, (FL_SINGLETON|FL_FREEZE)) == FL_SINGLETON) { - OBJ_FREEZE_RAW(klass); + OBJ_FREEZE(klass); } } } diff --git a/compile.c b/compile.c index d5fa6a5c7451be..cd63e4ba507a7e 100644 --- a/compile.c +++ b/compile.c @@ -10009,7 +10009,7 @@ compile_shareable_literal_constant(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_pa case NODE_ZLIST:{ VALUE lit = rb_ary_new(); - OBJ_FREEZE_RAW(lit); + OBJ_FREEZE(lit); ADD_INSN1(ret, node, putobject, lit); RB_OBJ_WRITTEN(iseq, Qundef, lit); *value_p = lit; diff --git a/complex.c b/complex.c index 4e2bff5df427aa..ff278f80fae3a6 100644 --- a/complex.c +++ b/complex.c @@ -397,7 +397,7 @@ nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag) RCOMPLEX_SET_REAL(obj, real); RCOMPLEX_SET_IMAG(obj, imag); - OBJ_FREEZE_RAW((VALUE)obj); + OBJ_FREEZE((VALUE)obj); return (VALUE)obj; } @@ -1717,7 +1717,7 @@ nucomp_loader(VALUE self, VALUE a) RCOMPLEX_SET_REAL(dat, rb_ivar_get(a, id_i_real)); RCOMPLEX_SET_IMAG(dat, rb_ivar_get(a, id_i_imag)); - OBJ_FREEZE_RAW(self); + OBJ_FREEZE(self); return self; } diff --git a/rational.c b/rational.c index 3b82016f323087..014cbb6c6adf87 100644 --- a/rational.c +++ b/rational.c @@ -418,7 +418,7 @@ nurat_s_new_internal(VALUE klass, VALUE num, VALUE den) RATIONAL_SET_NUM((VALUE)obj, num); RATIONAL_SET_DEN((VALUE)obj, den); - OBJ_FREEZE_RAW((VALUE)obj); + OBJ_FREEZE((VALUE)obj); return (VALUE)obj; } @@ -1847,7 +1847,7 @@ nurat_loader(VALUE self, VALUE a) nurat_canonicalize(&num, &den); RATIONAL_SET_NUM((VALUE)dat, num); RATIONAL_SET_DEN((VALUE)dat, den); - OBJ_FREEZE_RAW(self); + OBJ_FREEZE(self); return self; } diff --git a/ruby.c b/ruby.c index fb60551c3fc050..e939320f1f63d3 100644 --- a/ruby.c +++ b/ruby.c @@ -706,11 +706,11 @@ ruby_init_loadpath(void) p -= bindir_len; archlibdir = rb_str_subseq(sopath, 0, p - libpath); rb_str_cat_cstr(archlibdir, libdir); - OBJ_FREEZE_RAW(archlibdir); + OBJ_FREEZE(archlibdir); } else if (p - libpath >= libdir_len && !strncmp(p - libdir_len, libdir, libdir_len)) { archlibdir = rb_str_subseq(sopath, 0, (p2 ? p2 : p) - libpath); - OBJ_FREEZE_RAW(archlibdir); + OBJ_FREEZE(archlibdir); p -= libdir_len; } #ifdef ENABLE_MULTIARCH @@ -741,7 +741,7 @@ ruby_init_loadpath(void) #endif rb_gc_register_address(&ruby_prefix_path); ruby_prefix_path = PREFIX_PATH(); - OBJ_FREEZE_RAW(ruby_prefix_path); + OBJ_FREEZE(ruby_prefix_path); if (!archlibdir) archlibdir = ruby_prefix_path; rb_gc_register_address(&ruby_archlibdir_path); ruby_archlibdir_path = archlibdir; diff --git a/string.c b/string.c index 040228844da0cb..83bb91f17be6c4 100644 --- a/string.c +++ b/string.c @@ -379,7 +379,7 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t data, int exist RSTRING(str)->len, ENCODING_GET(str)); } - OBJ_FREEZE_RAW(str); + OBJ_FREEZE(str); } else { if (!OBJ_FROZEN(str) || CHILLED_STRING_P(str)) { @@ -415,7 +415,7 @@ rb_fstring(VALUE str) bare = BARE_STRING_P(str); if (!bare) { if (STR_EMBED_P(str)) { - OBJ_FREEZE_RAW(str); + OBJ_FREEZE(str); return str; } @@ -432,7 +432,7 @@ rb_fstring(VALUE str) if (!bare) { str_replace_shared_without_enc(str, fstr); - OBJ_FREEZE_RAW(str); + OBJ_FREEZE(str); return str; } return fstr; diff --git a/struct.c b/struct.c index e82bcc3e032804..544228f76b9582 100644 --- a/struct.c +++ b/struct.c @@ -136,7 +136,7 @@ struct_set_members(VALUE klass, VALUE /* frozen hidden array */ members) j = struct_member_pos_probe(j, mask); } } - OBJ_FREEZE_RAW(back); + OBJ_FREEZE(back); } rb_ivar_set(klass, id_members, members); rb_ivar_set(klass, id_back_members, back); @@ -422,7 +422,7 @@ struct_make_members_list(va_list ar) } ary = rb_hash_keys(list); RBASIC_CLEAR_CLASS(ary); - OBJ_FREEZE_RAW(ary); + OBJ_FREEZE(ary); return ary; } @@ -682,7 +682,7 @@ rb_struct_s_def(int argc, VALUE *argv, VALUE klass) } rest = rb_hash_keys(rest); RBASIC_CLEAR_CLASS(rest); - OBJ_FREEZE_RAW(rest); + OBJ_FREEZE(rest); if (NIL_P(name)) { st = anonymous_struct(klass); } @@ -794,7 +794,7 @@ VALUE rb_struct_initialize(VALUE self, VALUE values) { rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), self); - if (rb_obj_is_kind_of(self, rb_cData)) OBJ_FREEZE_RAW(self); + if (rb_obj_is_kind_of(self, rb_cData)) OBJ_FREEZE(self); RB_GC_GUARD(values); return Qnil; } @@ -1685,7 +1685,7 @@ rb_data_s_def(int argc, VALUE *argv, VALUE klass) } rest = rb_hash_keys(rest); RBASIC_CLEAR_CLASS(rest); - OBJ_FREEZE_RAW(rest); + OBJ_FREEZE(rest); data_class = anonymous_struct(klass); setup_data(data_class, rest); if (rb_block_given_p()) { @@ -1802,7 +1802,7 @@ rb_data_initialize_m(int argc, const VALUE *argv, VALUE self) rb_hash_foreach(argv[0], struct_hash_set_i, (VALUE)&arg); // Freeze early before potentially raising, so that we don't leave an // unfrozen copy on the heap, which could get exposed via ObjectSpace. - OBJ_FREEZE_RAW(self); + OBJ_FREEZE(self); if (arg.unknown_keywords != Qnil) { rb_exc_raise(rb_keyword_error_new("unknown", arg.unknown_keywords)); } @@ -1814,7 +1814,7 @@ static VALUE rb_data_init_copy(VALUE copy, VALUE s) { copy = rb_struct_init_copy(copy, s); - RB_OBJ_FREEZE_RAW(copy); + RB_OBJ_FREEZE(copy); return copy; } diff --git a/thread.c b/thread.c index 196f9092b49ebb..b8ba61e188bb2e 100644 --- a/thread.c +++ b/thread.c @@ -2281,7 +2281,7 @@ rb_thread_s_handle_interrupt(VALUE self, VALUE mask_arg) mask = mask_arg; } else if (RB_TYPE_P(mask, T_HASH)) { - OBJ_FREEZE_RAW(mask); + OBJ_FREEZE(mask); } rb_ary_push(th->pending_interrupt_mask_stack, mask); @@ -5846,7 +5846,7 @@ rb_uninterruptible(VALUE (*b_proc)(VALUE), VALUE data) rb_thread_t *cur_th = GET_THREAD(); rb_hash_aset(interrupt_mask, rb_cObject, sym_never); - OBJ_FREEZE_RAW(interrupt_mask); + OBJ_FREEZE(interrupt_mask); rb_ary_push(cur_th->pending_interrupt_mask_stack, interrupt_mask); VALUE ret = rb_ensure(b_proc, data, uninterruptible_exit, Qnil); diff --git a/vm_args.c b/vm_args.c index 9df175eaa94a79..1a78e96776d53b 100644 --- a/vm_args.c +++ b/vm_args.c @@ -1021,7 +1021,7 @@ vm_caller_setup_arg_block(const rb_execution_context_t *ec, rb_control_frame_t * VALUE callback_arg = rb_ary_hidden_new(2); rb_ary_push(callback_arg, block_code); rb_ary_push(callback_arg, ref); - OBJ_FREEZE_RAW(callback_arg); + OBJ_FREEZE(callback_arg); func = rb_func_lambda_new(refine_sym_proc_call, callback_arg, 1, UNLIMITED_ARGUMENTS); rb_hash_aset(ref, block_code, func); } From e5df8897fe999c77a2e25a85289ec286d0462617 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 16 Apr 2024 11:16:19 -0400 Subject: [PATCH 19/39] Don't check for thread in gc_sweep_page We should always have a thread when we sweep so we don't need to check that it exists. --- gc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/gc.c b/gc.c index a08a151efa6699..2a5b36dab7cf4b 100644 --- a/gc.c +++ b/gc.c @@ -5462,10 +5462,7 @@ gc_sweep_page(rb_objspace_t *objspace, rb_heap_t *heap, struct gc_sweep_context sweep_page->size_pool->total_freed_objects += ctx->freed_slots; if (heap_pages_deferred_final && !finalizing) { - rb_thread_t *th = GET_THREAD(); - if (th) { - gc_finalize_deferred_register(objspace); - } + gc_finalize_deferred_register(objspace); } #if RGENGC_CHECK_MODE From d6debba817da921d8bc9a3fdb6b4bcbe3d7b0859 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 16 Apr 2024 13:25:23 -0400 Subject: [PATCH 20/39] Don't check for dynamic symbol in gc_is_moveable_obj All GC managed symbols are dynamic symbols so we don't need to check it. --- gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gc.c b/gc.c index 2a5b36dab7cf4b..acf81ef1301844 100644 --- a/gc.c +++ b/gc.c @@ -9519,7 +9519,7 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj) case T_ZOMBIE: return FALSE; case T_SYMBOL: - if (DYNAMIC_SYM_P(obj) && (RSYMBOL(obj)->id & ~ID_SCOPE_MASK)) { + if (RSYMBOL(obj)->id & ~ID_SCOPE_MASK) { return FALSE; } /* fall through */ From f34409bf8782481deabec6c577abd66373134af9 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 16 Apr 2024 21:15:12 -0400 Subject: [PATCH 21/39] [ruby/prism] Fix up more clang-analyzer failures https://github.com/ruby/prism/commit/f9a1abbc64 --- prism/options.c | 49 +++++++++++++++++++++++++---------------- prism/util/pm_integer.c | 4 ++++ 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/prism/options.c b/prism/options.c index 2854b765b9323b..4d0d6dbc49a70c 100644 --- a/prism/options.c +++ b/prism/options.c @@ -47,29 +47,40 @@ pm_options_command_line_set(pm_options_t *options, uint8_t command_line) { */ PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const char *version, size_t length) { - if (version == NULL && length == 0) { - options->version = PM_OPTIONS_VERSION_LATEST; - return true; - } + switch (length) { + case 0: + if (version == NULL) { + options->version = PM_OPTIONS_VERSION_LATEST; + return true; + } - if (length == 5) { - if (strncmp(version, "3.3.0", length) == 0) { - options->version = PM_OPTIONS_VERSION_CRUBY_3_3_0; - return true; - } + return false; + case 5: + assert(version != NULL); - if (strncmp(version, "3.4.0", length) == 0) { - options->version = PM_OPTIONS_VERSION_LATEST; - return true; - } - } + if (strncmp(version, "3.3.0", length) == 0) { + options->version = PM_OPTIONS_VERSION_CRUBY_3_3_0; + return true; + } - if (length == 6 && strncmp(version, "latest", length) == 0) { - options->version = PM_OPTIONS_VERSION_LATEST; - return true; - } + if (strncmp(version, "3.4.0", length) == 0) { + options->version = PM_OPTIONS_VERSION_LATEST; + return true; + } + + return false; + case 6: + assert(version != NULL); - return false; + if (strncmp(version, "latest", length) == 0) { + options->version = PM_OPTIONS_VERSION_LATEST; + return true; + } + + return false; + default: + return false; + } } // For some reason, GCC analyzer thinks we're leaking allocated scopes and diff --git a/prism/util/pm_integer.c b/prism/util/pm_integer.c index 50210f0cb1cac6..0739662e98037b 100644 --- a/prism/util/pm_integer.c +++ b/prism/util/pm_integer.c @@ -194,7 +194,11 @@ karatsuba_multiply(pm_integer_t *destination, pm_integer_t *left, pm_integer_t * size_t length = left_length + right_length; uint32_t *values = (uint32_t*) xcalloc(length, sizeof(uint32_t)); + + assert(z0.values != NULL); memcpy(values, z0.values, sizeof(uint32_t) * z0.length); + + assert(z2.values != NULL); memcpy(values + 2 * half, z2.values, sizeof(uint32_t) * z2.length); uint32_t carry = 0; From 75154dec73e1329693866e3a88cb9febb7635417 Mon Sep 17 00:00:00 2001 From: Jean byroot Boussier Date: Wed, 17 Apr 2024 03:29:09 +0200 Subject: [PATCH 22/39] [ruby/stringio] strio_read: preserve buffer encoding on partial reads (https://github.com/ruby/stringio/pull/95) [[Bug #20418]](https://bugs.ruby-lang.org/issues/20418) Ruby IO#read preserves the encoding on partial read, but change it when reading the whole IO from commit https://github.com/ruby/ruby/commit/0ca7036682da: > * io.c (read_all): should associate default external encoding. > * io.c (io_read): should NOT associate default external encoding. https://github.com/ruby/stringio/commit/073172da31 Co-authored-by: Jean Boussier --- ext/stringio/stringio.c | 5 ++--- test/stringio/test_stringio.rb | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index f0e5ee4e85ff09..820b8228a31fb7 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -1623,10 +1623,9 @@ strio_read(int argc, VALUE *argv, VALUE self) if (len > rest) len = rest; rb_str_resize(str, len); MEMCPY(RSTRING_PTR(str), RSTRING_PTR(ptr->string) + ptr->pos, char, len); - if (binary) - rb_enc_associate(str, rb_ascii8bit_encoding()); - else + if (!binary) { rb_enc_copy(str, ptr->string); + } } ptr->pos += RSTRING_LEN(str); return str; diff --git a/test/stringio/test_stringio.rb b/test/stringio/test_stringio.rb index e17cd0abb11a01..90316505819b8c 100644 --- a/test/stringio/test_stringio.rb +++ b/test/stringio/test_stringio.rb @@ -700,6 +700,18 @@ def test_read s.force_encoding(Encoding::US_ASCII) assert_same(s, f.read(nil, s)) assert_string("", Encoding::UTF_8, s, bug13806) + + bug20418 = '[Bug #20418] ™€®'.b + f = StringIO.new(bug20418) + s = "" + assert_equal(Encoding::UTF_8, s.encoding, bug20418) + f.read(4, s) + assert_equal(Encoding::UTF_8, s.encoding, bug20418) + + f.rewind + s = "" + f.read(nil, s) + assert_equal(Encoding::ASCII_8BIT, s.encoding, bug20418) end def test_readpartial @@ -711,8 +723,8 @@ def test_readpartial assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.readpartial(f.size)) f.rewind # not empty buffer - s = '0123456789' - assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.readpartial(f.size, s)) + s = '0123456789'.b + assert_equal("\u3042\u3044".b, f.readpartial(f.size, s)) end def test_read_nonblock @@ -736,8 +748,8 @@ def test_read_nonblock_no_exceptions assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read_nonblock(f.size)) f.rewind # not empty buffer - s = '0123456789' - assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read_nonblock(f.size, s)) + s = '0123456789'.b + assert_equal("\u3042\u3044".b, f.read_nonblock(f.size, s)) end def test_sysread From 0b630d644128da611c73fd9fc28d3ee2e9cd80c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 02:08:14 +0000 Subject: [PATCH 23/39] Bump ruby/setup-ruby from 1.173.0 to 1.174.0 Bumps [ruby/setup-ruby](https://github.com/ruby/setup-ruby) from 1.173.0 to 1.174.0. - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Commits](https://github.com/ruby/setup-ruby/compare/5f19ec79cedfadb78ab837f95b87734d0003c899...6bd3d993c602f6b675728ebaecb2b569ff86e99b) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/annocheck.yml | 2 +- .github/workflows/baseruby.yml | 2 +- .github/workflows/check_dependencies.yml | 2 +- .github/workflows/mingw.yml | 2 +- .github/workflows/rjit-bindgen.yml | 2 +- .github/workflows/spec_guards.yml | 2 +- .github/workflows/ubuntu.yml | 2 +- .github/workflows/wasm.yml | 2 +- .github/workflows/windows.yml | 2 +- .github/workflows/yjit-ubuntu.yml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/annocheck.yml b/.github/workflows/annocheck.yml index bc5b81a9b99b2c..f3f496c29ac593 100644 --- a/.github/workflows/annocheck.yml +++ b/.github/workflows/annocheck.yml @@ -74,7 +74,7 @@ jobs: builddir: build makeup: true - - uses: ruby/setup-ruby@5f19ec79cedfadb78ab837f95b87734d0003c899 # v1.173.0 + - uses: ruby/setup-ruby@6bd3d993c602f6b675728ebaecb2b569ff86e99b # v1.174.0 with: ruby-version: '3.0' bundler: none diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml index 2bc1e39e0c807a..50ff7014fff342 100644 --- a/.github/workflows/baseruby.yml +++ b/.github/workflows/baseruby.yml @@ -51,7 +51,7 @@ jobs: - ruby-3.3 steps: - - uses: ruby/setup-ruby@5f19ec79cedfadb78ab837f95b87734d0003c899 # v1.173.0 + - uses: ruby/setup-ruby@6bd3d993c602f6b675728ebaecb2b569ff86e99b # v1.174.0 with: ruby-version: ${{ matrix.ruby }} bundler: none diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml index 5187138be97c8e..a5e491d7a44cec 100644 --- a/.github/workflows/check_dependencies.yml +++ b/.github/workflows/check_dependencies.yml @@ -55,7 +55,7 @@ jobs: - uses: ./.github/actions/setup/directories - - uses: ruby/setup-ruby@5f19ec79cedfadb78ab837f95b87734d0003c899 # v1.173.0 + - uses: ruby/setup-ruby@6bd3d993c602f6b675728ebaecb2b569ff86e99b # v1.174.0 with: ruby-version: '3.0' bundler: none diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index 1ed83de53521a3..d8c075fc7a64ab 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -66,7 +66,7 @@ jobs: steps: - name: Set up Ruby & MSYS2 - uses: ruby/setup-ruby@5f19ec79cedfadb78ab837f95b87734d0003c899 # v1.173.0 + uses: ruby/setup-ruby@6bd3d993c602f6b675728ebaecb2b569ff86e99b # v1.174.0 with: ruby-version: ${{ matrix.baseruby }} diff --git a/.github/workflows/rjit-bindgen.yml b/.github/workflows/rjit-bindgen.yml index 65f7b080a3d678..b77d79e83ab2e4 100644 --- a/.github/workflows/rjit-bindgen.yml +++ b/.github/workflows/rjit-bindgen.yml @@ -47,7 +47,7 @@ jobs: steps: - name: Set up Ruby - uses: ruby/setup-ruby@5f19ec79cedfadb78ab837f95b87734d0003c899 # v1.173.0 + uses: ruby/setup-ruby@6bd3d993c602f6b675728ebaecb2b569ff86e99b # v1.174.0 with: ruby-version: '3.1' diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml index f4d8c378373eb0..bb4bf8441f85e5 100644 --- a/.github/workflows/spec_guards.yml +++ b/.github/workflows/spec_guards.yml @@ -47,7 +47,7 @@ jobs: steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - uses: ruby/setup-ruby@5f19ec79cedfadb78ab837f95b87734d0003c899 # v1.173.0 + - uses: ruby/setup-ruby@6bd3d993c602f6b675728ebaecb2b569ff86e99b # v1.174.0 with: ruby-version: ${{ matrix.ruby }} bundler: none diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 42b485700d3838..8f70fcfaaf6d35 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -67,7 +67,7 @@ jobs: with: arch: ${{ matrix.arch }} - - uses: ruby/setup-ruby@5f19ec79cedfadb78ab837f95b87734d0003c899 # v1.173.0 + - uses: ruby/setup-ruby@6bd3d993c602f6b675728ebaecb2b569ff86e99b # v1.174.0 with: ruby-version: '3.0' bundler: none diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index 5ec4bfafaed22e..1e0a0574bea660 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -100,7 +100,7 @@ jobs: run: | echo "WASI_SDK_PATH=/opt/wasi-sdk" >> $GITHUB_ENV - - uses: ruby/setup-ruby@5f19ec79cedfadb78ab837f95b87734d0003c899 # v1.173.0 + - uses: ruby/setup-ruby@6bd3d993c602f6b675728ebaecb2b569ff86e99b # v1.174.0 with: ruby-version: '3.0' bundler: none diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 56e2711b5b9d5d..e1a18297551bd9 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -91,7 +91,7 @@ jobs: ${{ steps.find-tools.outputs.needs }} if: ${{ steps.find-tools.outputs.needs != '' }} - - uses: ruby/setup-ruby@5f19ec79cedfadb78ab837f95b87734d0003c899 # v1.173.0 + - uses: ruby/setup-ruby@6bd3d993c602f6b675728ebaecb2b569ff86e99b # v1.174.0 with: ruby-version: '3.0' bundler: none diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml index 92ff9eadaed607..dcf7e1874af78f 100644 --- a/.github/workflows/yjit-ubuntu.yml +++ b/.github/workflows/yjit-ubuntu.yml @@ -145,7 +145,7 @@ jobs: if: ${{ matrix.rust_version }} run: rustup install ${{ matrix.rust_version }} --profile minimal - - uses: ruby/setup-ruby@5f19ec79cedfadb78ab837f95b87734d0003c899 # v1.173.0 + - uses: ruby/setup-ruby@6bd3d993c602f6b675728ebaecb2b569ff86e99b # v1.174.0 with: ruby-version: '3.0' bundler: none From f9f301800199e7b5b9a6e92cf726cd0214d417a4 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Wed, 17 Apr 2024 16:30:47 +0900 Subject: [PATCH 24/39] `ISeq#to_a` respects `use_block` status ```ruby b = RubyVM::InstructionSequence.compile('def f = yield; def g = nil').to_a pp b #=> ... {:use_block=>true}, ... ``` --- compile.c | 4 ++++ iseq.c | 1 + test/ruby/test_iseq.rb | 12 ++++++++++++ 3 files changed, 17 insertions(+) diff --git a/compile.c b/compile.c index cd63e4ba507a7e..b980d6a32cef56 100644 --- a/compile.c +++ b/compile.c @@ -11761,6 +11761,10 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, ISEQ_BODY(iseq)->param.flags.ambiguous_param0 = TRUE; } + if (Qtrue == rb_hash_aref(params, SYM(use_block))) { + ISEQ_BODY(iseq)->param.flags.use_block = TRUE; + } + if (int_param(&i, params, SYM(kwrest))) { struct rb_iseq_param_keyword *keyword = (struct rb_iseq_param_keyword *)ISEQ_BODY(iseq)->param.keyword; if (keyword == NULL) { diff --git a/iseq.c b/iseq.c index 6d4fa5bd336e80..15635332ffbc3e 100644 --- a/iseq.c +++ b/iseq.c @@ -3200,6 +3200,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq) } if (iseq_body->param.flags.has_kwrest) rb_hash_aset(params, ID2SYM(rb_intern("kwrest")), INT2FIX(keyword->rest_start)); if (iseq_body->param.flags.ambiguous_param0) rb_hash_aset(params, ID2SYM(rb_intern("ambiguous_param0")), Qtrue); + if (iseq_body->param.flags.use_block) rb_hash_aset(params, ID2SYM(rb_intern("use_block")), Qtrue); } /* body */ diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb index dc84d8bd7c4b51..a31605885a5c9b 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -827,6 +827,18 @@ def test_compile_prism_with_file end end + def block_using_method + yield + end + + def block_unused_method + end + + def test_unused_param + assert_equal true, RubyVM::InstructionSequence.of(method(:block_using_method)).to_a.dig(11, :use_block) + assert_equal nil, RubyVM::InstructionSequence.of(method(:block_unused_method)).to_a.dig(11, :use_block) + end + def test_compile_prism_with_invalid_object_type assert_raise(TypeError) do RubyVM::InstructionSequence.compile_prism(Object.new) From d31eda8eb636b9cc1ef343df5688f1abea3409c9 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Tue, 16 Apr 2024 08:29:25 +0200 Subject: [PATCH 25/39] Add NEWS entry for [[Feature #20429]] Followup: https://github.com/ruby/ruby/pull/10532 --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index 98e4f17cf7a3a4..f3368421a9a10e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -122,6 +122,11 @@ See GitHub releases like [GitHub Releases of Logger](https://github.com/ruby/log a warning on verbose mode (`-w`). [[Feature #15554]] +* Redefining some core methods that are specially optimized by the interpeter + and JIT like `String.freeze` or `Integer#+` now emits a performance class + warning (`-W:performance` or `Warning[:performance] = true`). + [[Feature #20429]] + [Feature #13557]: https://bugs.ruby-lang.org/issues/13557 [Feature #15554]: https://bugs.ruby-lang.org/issues/15554 [Feature #16495]: https://bugs.ruby-lang.org/issues/16495 From eac3dee9cdefcc414af832c99a95383a38790d1c Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Wed, 17 Apr 2024 09:59:50 +0200 Subject: [PATCH 26/39] test_uplus_minus: Use a different string literal This test fail relatively frequently and it's unclear what is happening. ``` str: {"address":"0x7fbdeb26d4e0", "type":"STRING", "shape_id":1, "slot_size":40, "class":"0x7fbdd1e0ec50", "frozen":true, "embedded":true, "fstring":true, "bytesize":3, "value":"bar", "encoding":"UTF-8", "coderange":"7bit", "memsize":40, "flags":{"wb_protected":true, "old":true, "uncollectible":true, "marked":true}} bar: {"address":"0x7fbdd0a8b138", "type":"STRING", "shape_id":1, "slot_size":40, "class":"0x7fbdd1e0ec50", "frozen":true, "embedded":true, "fstring":true, "bytesize":3, "value":"bar", "encoding":"UTF-8", "coderange":"7bit", "memsize":40, "flags":{"wb_protected":true}} ``` The `"bar".freeze` literal correctly put an old-gen fstring on the stack. But `-%w(b a r).join('')` returns a young-gen fstring, which suggest it somehow failed to find the old one in the `frozen_strings` table. This could be caused by another test corrupting the table, or corrupting the `"bar"` fstring. By using a different literal value we can learn whether the bug is specific to `"bar"` (used in many tests) or more general. --- test/ruby/test_string.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 13261eacdd1f79..ebe85dac826d6e 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -3358,7 +3358,7 @@ def test_uplus_minus require 'objspace' - str = "bar".freeze + str = "test_uplus_minus_str".freeze assert_includes ObjectSpace.dump(str), '"fstring":true' assert_predicate(str, :frozen?) @@ -3368,7 +3368,7 @@ def test_uplus_minus assert_not_same(str, +str) assert_same(str, -str) - bar = -%w(b a r).join('') + bar = -%w(test uplus minus str).join('_') assert_same(str, bar, "uminus deduplicates [Feature #13077] str: #{ObjectSpace.dump(str)} bar: #{ObjectSpace.dump(bar)}") end From 7bc66a366ded3ae2d07a418e17a9da6ee24612fd Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Wed, 17 Apr 2024 17:40:20 +0900 Subject: [PATCH 27/39] skip on Prism generated iseq --- test/ruby/test_iseq.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb index a31605885a5c9b..dbf91fe8c94025 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -835,8 +835,14 @@ def block_unused_method end def test_unused_param - assert_equal true, RubyVM::InstructionSequence.of(method(:block_using_method)).to_a.dig(11, :use_block) - assert_equal nil, RubyVM::InstructionSequence.of(method(:block_unused_method)).to_a.dig(11, :use_block) + a = RubyVM::InstructionSequence.of(method(:block_using_method)).to_a + + omit 'TODO: Prism' if a.dig(4, :parser) != :"parse.y" + + assert_equal true, a.dig(11, :use_block) + + b = RubyVM::InstructionSequence.of(method(:block_unused_method)).to_a + assert_equal nil, b.dig(11, :use_block) end def test_compile_prism_with_invalid_object_type From 09638741ba4d9547a0e48af8c767744fb1d7f68d Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 17 Apr 2024 16:03:05 +0900 Subject: [PATCH 28/39] [Feature #20335] `Thread.each_caller_location` arguments Accecpt the same arguments as `caller` and `caller_locations`. --- lib/bundled_gems.rb | 14 +------ .../core/thread/each_caller_location_spec.rb | 4 +- spec/ruby/optional/capi/spec_helper.rb | 7 ---- test/ruby/test_backtrace.rb | 8 ++++ vm_backtrace.c | 42 +++++++++++++------ 5 files changed, 42 insertions(+), 33 deletions(-) diff --git a/lib/bundled_gems.rb b/lib/bundled_gems.rb index e61c1ad231b297..a340463c9844e5 100644 --- a/lib/bundled_gems.rb +++ b/lib/bundled_gems.rb @@ -143,18 +143,8 @@ def self.build_message(gem) # Additionally, we need to skip Bootsnap and Zeitwerk if present, these # gems decorate Kernel#require, so they are not really the ones issuing # the require call users should be warned about. Those are upwards. - frames_to_skip = 2 - location = nil - Thread.each_caller_location do |cl| - if frames_to_skip >= 1 - frames_to_skip -= 1 - next - end - - if cl.base_label != "require" - location = cl.path - break - end + location = Thread.each_caller_location(2) do |cl| + break cl.path unless cl.base_label == "require" end if location && File.file?(location) && !location.start_with?(Gem::BUNDLED_GEMS::LIBDIR) diff --git a/spec/ruby/core/thread/each_caller_location_spec.rb b/spec/ruby/core/thread/each_caller_location_spec.rb index dbece06cd8183e..29c271789b5225 100644 --- a/spec/ruby/core/thread/each_caller_location_spec.rb +++ b/spec/ruby/core/thread/each_caller_location_spec.rb @@ -40,10 +40,10 @@ }.should raise_error(LocalJumpError, "no block given") end - it "doesn't accept positional and keyword arguments" do + it "doesn't accept keyword arguments" do -> { Thread.each_caller_location(12, foo: 10) {} - }.should raise_error(ArgumentError, "wrong number of arguments (given 2, expected 0)") + }.should raise_error(ArgumentError); end end end diff --git a/spec/ruby/optional/capi/spec_helper.rb b/spec/ruby/optional/capi/spec_helper.rb index 2691aa1332200a..c7364484b4ed93 100644 --- a/spec/ruby/optional/capi/spec_helper.rb +++ b/spec/ruby/optional/capi/spec_helper.rb @@ -33,12 +33,6 @@ def compile_extension(name) ruby_header = "#{rubyhdrdir}/ruby.h" abi_header = "#{rubyhdrdir}/ruby/internal/abi.h" - if RbConfig::CONFIG["ENABLE_SHARED"] == "yes" - # below is defined since 2.1, except for mswin, and maybe other platforms - libdirname = RbConfig::CONFIG.fetch 'libdirname', 'libdir' - libruby = "#{RbConfig::CONFIG[libdirname]}/#{RbConfig::CONFIG['LIBRUBY']}" - end - begin mtime = File.mtime(lib) rescue Errno::ENOENT @@ -49,7 +43,6 @@ def compile_extension(name) when mtime <= File.mtime("#{spec_ext_dir}/#{ext}.c") when mtime <= File.mtime(ruby_header) when (mtime <= File.mtime(abi_header) rescue nil) - when libruby && mtime <= File.mtime(libruby) else return lib # up-to-date end diff --git a/test/ruby/test_backtrace.rb b/test/ruby/test_backtrace.rb index cfc65faacb1ab1..fca7b620302680 100644 --- a/test/ruby/test_backtrace.rb +++ b/test/ruby/test_backtrace.rb @@ -155,6 +155,10 @@ def test_caller_with_nil_length end def test_each_backtrace_location + assert_nil(Thread.each_caller_location {}) + + assert_raise(LocalJumpError) {Thread.each_caller_location} + i = 0 cl = caller_locations(1, 1)[0]; ecl = Thread.each_caller_location{|x| i+=1; break x if i == 1} assert_equal(cl.to_s, ecl.to_s) @@ -181,6 +185,10 @@ def test_each_backtrace_location assert_raise(StopIteration) { ecl.next } + + ary = [] + cl = caller_locations(1, 2); Thread.each_caller_location(1, 2) {|x| ary << x} + assert_equal(cl.map(&:to_s), ary.map(&:to_s)) end def test_caller_locations_first_label diff --git a/vm_backtrace.c b/vm_backtrace.c index 3fe816930da2de..22b28368d74d77 100644 --- a/vm_backtrace.c +++ b/vm_backtrace.c @@ -1170,17 +1170,17 @@ rb_make_backtrace(void) return rb_ec_backtrace_str_ary(GET_EC(), BACKTRACE_START, ALL_BACKTRACE_LINES); } -static VALUE -ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *argv, int lev_default, int lev_plus, int to_str) +static long +ec_backtrace_range(const rb_execution_context_t *ec, int argc, const VALUE *argv, int lev_default, int lev_plus, long *len_ptr) { - VALUE level, vn; + VALUE level, vn, opts; long lev, n; - VALUE btval; - VALUE r; - int too_large; - rb_scan_args(argc, argv, "02", &level, &vn); + rb_scan_args(argc, argv, "02:", &level, &vn, &opts); + if (!NIL_P(opts)) { + rb_get_kwargs(opts, (ID []){0}, 0, 0, NULL); + } if (argc == 2 && NIL_P(vn)) argc--; switch (argc) { @@ -1201,7 +1201,7 @@ ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *arg n = ALL_BACKTRACE_LINES; break; case Qnil: - return Qnil; + return -1; default: lev = beg + lev_plus; n = len; @@ -1225,6 +1225,20 @@ ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *arg break; } + *len_ptr = n; + return lev; +} + +static VALUE +ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *argv, int lev_default, int lev_plus, int to_str) +{ + long lev, n; + VALUE btval, r; + int too_large; + + lev = ec_backtrace_range(ec, argc, argv, lev_default, lev_plus, &n); + if (lev < 0) return Qnil; + if (n == 0) { return rb_ary_new(); } @@ -1354,15 +1368,19 @@ rb_f_caller_locations(int argc, VALUE *argv, VALUE _) /* * call-seq: - * Thread.each_caller_location{ |loc| ... } -> nil + * Thread.each_caller_location(...) { |loc| ... } -> nil * * Yields each frame of the current execution stack as a * backtrace location object. */ static VALUE -each_caller_location(VALUE unused) +each_caller_location(int argc, VALUE *argv, VALUE _) { - rb_ec_partial_backtrace_object(GET_EC(), 2, ALL_BACKTRACE_LINES, NULL, FALSE, TRUE); + rb_execution_context_t *ec = GET_EC(); + long n, lev = ec_backtrace_range(ec, argc, argv, 1, 1, &n); + if (lev >= 0 && n != 0) { + rb_ec_partial_backtrace_object(ec, lev, n, NULL, FALSE, TRUE); + } return Qnil; } @@ -1442,7 +1460,7 @@ Init_vm_backtrace(void) rb_define_global_function("caller", rb_f_caller, -1); rb_define_global_function("caller_locations", rb_f_caller_locations, -1); - rb_define_singleton_method(rb_cThread, "each_caller_location", each_caller_location, 0); + rb_define_singleton_method(rb_cThread, "each_caller_location", each_caller_location, -1); } /* debugger API */ From 55b68d6cdc19da22eaae0a8dda6a2ab0ac65ac99 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 17 Apr 2024 19:16:00 +0900 Subject: [PATCH 29/39] Revert an accidentally merged change [ci skip] --- spec/ruby/optional/capi/spec_helper.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spec/ruby/optional/capi/spec_helper.rb b/spec/ruby/optional/capi/spec_helper.rb index c7364484b4ed93..2691aa1332200a 100644 --- a/spec/ruby/optional/capi/spec_helper.rb +++ b/spec/ruby/optional/capi/spec_helper.rb @@ -33,6 +33,12 @@ def compile_extension(name) ruby_header = "#{rubyhdrdir}/ruby.h" abi_header = "#{rubyhdrdir}/ruby/internal/abi.h" + if RbConfig::CONFIG["ENABLE_SHARED"] == "yes" + # below is defined since 2.1, except for mswin, and maybe other platforms + libdirname = RbConfig::CONFIG.fetch 'libdirname', 'libdir' + libruby = "#{RbConfig::CONFIG[libdirname]}/#{RbConfig::CONFIG['LIBRUBY']}" + end + begin mtime = File.mtime(lib) rescue Errno::ENOENT @@ -43,6 +49,7 @@ def compile_extension(name) when mtime <= File.mtime("#{spec_ext_dir}/#{ext}.c") when mtime <= File.mtime(ruby_header) when (mtime <= File.mtime(abi_header) rescue nil) + when libruby && mtime <= File.mtime(libruby) else return lib # up-to-date end From e7493df7ac22c1257692251c97362ad55408a9fe Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Wed, 17 Apr 2024 11:46:01 +0200 Subject: [PATCH 30/39] Improve phrasing of ignored block warnings --- vm_insnhelper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 68a74a3e337208..00cd709526ab2e 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -3008,7 +3008,7 @@ warn_unused_block(const rb_callable_method_entry_t *cme, const rb_iseq_t *iseq, VALUE name = rb_gen_method_name(cme->defined_class, ISEQ_BODY(iseq)->location.base_label); if (!NIL_P(m_loc)) { - rb_warning("the passed block for '%"PRIsVALUE"' defined at %"PRIsVALUE":%"PRIsVALUE" may be ignored", + rb_warning("the block passed to '%"PRIsVALUE"' defined at %"PRIsVALUE":%"PRIsVALUE" may be ignored", name, RARRAY_AREF(m_loc, 0), RARRAY_AREF(m_loc, 1)); } else { From cc37c89c2f4253a6f39a36ad610d0ba89c4257e8 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 19 Mar 2024 15:03:11 +0900 Subject: [PATCH 31/39] Separate docs task from main to install-* [Feature #20347] --- common.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common.mk b/common.mk index 3fce9df761bf80..c2b24674668e95 100644 --- a/common.mk +++ b/common.mk @@ -337,7 +337,7 @@ YJIT_RUSTC_ARGS = --crate-name=yjit \ '--out-dir=$(CARGO_TARGET_DIR)/release/' \ $(top_srcdir)/yjit/src/lib.rs -all: $(SHOWFLAGS) main docs +all: $(SHOWFLAGS) main main: $(SHOWFLAGS) exts $(ENCSTATIC:static=lib)encs @$(NULLCMD) @@ -479,7 +479,7 @@ docs: srcs-doc $(DOCTARGETS) pkgconfig-data: $(ruby_pc) $(ruby_pc): $(srcdir)/template/ruby.pc.in config.status -install-all: docs pre-install-all do-install-all post-install-all +install-all: pre-install-all docs do-install-all post-install-all pre-install-all:: all pre-install-local pre-install-ext pre-install-gem pre-install-doc do-install-all: pre-install-all $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=all $(INSTALL_DOC_OPTS) From 945a0334c71412ddeeb540f68481eee40e250c61 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 17 Apr 2024 19:13:51 +0900 Subject: [PATCH 32/39] Update build and install document related https://blade.ruby-lang.org/ruby-dev/39325 --- doc/contributing/building_ruby.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/contributing/building_ruby.md b/doc/contributing/building_ruby.md index 2991385b94a6e6..4dabaca840e47f 100644 --- a/doc/contributing/building_ruby.md +++ b/doc/contributing/building_ruby.md @@ -96,11 +96,20 @@ 5. Build Ruby: ``` shell - make install + make ``` 6. [Run tests](testing_ruby.md) to confirm your build succeeded. +7. Install Ruby: + + ``` shell + make install + ``` + + - If you need to run `make install` with `sudo` and want to avoid document generation with different permissions, you can use + `make SUDO=sudo install`. + ### Unexplainable Build Errors If you are having unexplainable build errors, after saving all your work, try running `git clean -xfd` in the source root to remove all git ignored local files. If you are working from a source directory that's been updated several times, you may have temporary build artifacts from previous releases which can cause build failures. From 6ade36c06b7cef948099b8f5f483763498705d12 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 17 Apr 2024 23:08:47 +1200 Subject: [PATCH 33/39] `Fiber#raise` recursively raises on nested resuming_fiber. (#10482) * Improve consistency of `Fiber.current.raise`. --- cont.c | 8 ++++++- spec/ruby/core/fiber/raise_spec.rb | 34 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/cont.c b/cont.c index f7a4863f2cd270..2cbabba48900fc 100644 --- a/cont.c +++ b/cont.c @@ -3227,7 +3227,13 @@ rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass) static VALUE fiber_raise(rb_fiber_t *fiber, VALUE exception) { - if (FIBER_SUSPENDED_P(fiber) && !fiber->yielding) { + if (fiber == fiber_current()) { + rb_exc_raise(exception); + } + else if (fiber->resuming_fiber) { + return fiber_raise(fiber->resuming_fiber, exception); + } + else if (FIBER_SUSPENDED_P(fiber) && !fiber->yielding) { return fiber_transfer_kw(fiber, -1, &exception, RB_NO_KEYWORDS); } else { diff --git a/spec/ruby/core/fiber/raise_spec.rb b/spec/ruby/core/fiber/raise_spec.rb index eb4b39c8be55df..b3e021e6360b7a 100644 --- a/spec/ruby/core/fiber/raise_spec.rb +++ b/spec/ruby/core/fiber/raise_spec.rb @@ -91,6 +91,40 @@ fiber_two.resume.should == [:yield_one, :rescued] end + + ruby_version_is "3.4" do + it "raises on the resumed fiber" do + root_fiber = Fiber.current + f1 = Fiber.new { root_fiber.transfer } + f2 = Fiber.new { f1.resume } + f2.transfer + + -> do + f2.raise(RuntimeError, "Expected error") + end.should raise_error(RuntimeError, "Expected error") + end + + it "raises on itself" do + -> do + Fiber.current.raise(RuntimeError, "Expected error") + end.should raise_error(RuntimeError, "Expected error") + end + + it "should raise on parent fiber" do + f2 = nil + f1 = Fiber.new do + # This is equivalent to Kernel#raise: + f2.raise(RuntimeError, "Expected error") + end + f2 = Fiber.new do + f1.resume + end + + -> do + f2.resume + end.should raise_error(RuntimeError, "Expected error") + end + end end From e9d7478dedbd2b57530bc17efe8a9db9b8b2f280 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Wed, 17 Apr 2024 19:46:48 +0900 Subject: [PATCH 34/39] relax unused block warning for duck typing if a method `foo` uses a block, other (unrelated) method `foo` can receives a block. So try to relax the unused block warning condition. ```ruby class C0 def f = yield end class C1 < C0 def f = nil end [C0, C1].f{ block } # do not warn ``` --- compile.c | 23 ++++++++++++++++++----- test/ruby/test_method.rb | 14 ++++++++++++++ vm.c | 1 + vm_core.h | 1 + vm_insnhelper.c | 16 ++++++++++------ 5 files changed, 44 insertions(+), 11 deletions(-) diff --git a/compile.c b/compile.c index b980d6a32cef56..853fadf5b04892 100644 --- a/compile.c +++ b/compile.c @@ -1998,6 +1998,19 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, return arg_size; } +static void +iseq_set_use_block(rb_iseq_t *iseq) +{ + struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq); + if (!body->param.flags.use_block) { + body->param.flags.use_block = 1; + + rb_vm_t *vm = GET_VM(); + st_data_t key = (st_data_t)rb_intern_str(body->location.label); // String -> ID + st_insert(vm->unused_block_warning_table, key, 1); + } +} + static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *const node_args) { @@ -2099,7 +2112,7 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons if (block_id) { body->param.block_start = arg_size++; body->param.flags.has_block = TRUE; - body->param.flags.use_block = 1; + iseq_set_use_block(iseq); } iseq_calc_param_size(iseq); @@ -5920,7 +5933,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, ADD_INSN(ret, line_node, putnil); ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_YIELD), 0, PUSH_VAL(DEFINED_YIELD)); - ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.use_block = 1; + iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq); return; case NODE_BACK_REF: @@ -8632,7 +8645,7 @@ compile_builtin_attr(rb_iseq_t *iseq, const NODE *node) ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_INLINE_BLOCK; } else if (strcmp(RSTRING_PTR(string), "use_block") == 0) { - ISEQ_BODY(iseq)->param.flags.use_block = 1; + iseq_set_use_block(iseq); } else { goto unknown_arg; @@ -9481,7 +9494,7 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i } if (use_block && parent_block == NULL) { - ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.use_block = 1; + iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq); } flag |= VM_CALL_SUPER | VM_CALL_FCALL; @@ -9527,7 +9540,7 @@ compile_yield(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i ADD_SEQ(ret, args); ADD_INSN1(ret, node, invokeblock, new_callinfo(iseq, 0, FIX2INT(argc), flag, keywords, FALSE)); - ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.use_block = 1; + iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq); if (popped) { ADD_INSN(ret, node, pop); diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb index a41704cf069055..5301b51650b3cc 100644 --- a/test/ruby/test_method.rb +++ b/test/ruby/test_method.rb @@ -1692,5 +1692,19 @@ def f6 = super{} # zsuper / unuse assert_match(/-:23: warning.+f5/, err.join) assert_match(/-:24: warning.+f6/, err.join) end + + assert_in_out_err '-w', <<-'RUBY' do |_out, err, _status| + class C0 + def f = yield + end + + class C1 < C0 + def f = nil + end + + C1.new.f{} # do not warn on duck typing + RUBY + assert_equal 0, err.size, err.join("\n") + end end end diff --git a/vm.c b/vm.c index 3fb57e2eb6e500..cf2bed84e4d035 100644 --- a/vm.c +++ b/vm.c @@ -4254,6 +4254,7 @@ Init_BareVM(void) vm->negative_cme_table = rb_id_table_create(16); vm->overloaded_cme_table = st_init_numtable(); vm->constant_cache = rb_id_table_create(0); + vm->unused_block_warning_table = st_init_numtable(); // setup main thread th->nt = ZALLOC(struct rb_native_thread); diff --git a/vm_core.h b/vm_core.h index 9d6f8d87d0c682..2400b02c7e4042 100644 --- a/vm_core.h +++ b/vm_core.h @@ -773,6 +773,7 @@ typedef struct rb_vm_struct { st_table *ci_table; struct rb_id_table *negative_cme_table; st_table *overloaded_cme_table; // cme -> overloaded_cme + st_table *unused_block_warning_table; // This id table contains a mapping from ID to ICs. It does this with ID // keys and nested st_tables as values. The nested tables have ICs as keys diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 00cd709526ab2e..84ef21205338da 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -2971,9 +2971,9 @@ VALUE rb_gen_method_name(VALUE owner, VALUE name); // in vm_backtrace.c static void warn_unused_block(const rb_callable_method_entry_t *cme, const rb_iseq_t *iseq, void *pc) { - static st_table *dup_check_table = NULL; + rb_vm_t *vm = GET_VM(); + st_table *dup_check_table = vm->unused_block_warning_table; - st_data_t key = 0; union { VALUE v; unsigned char b[SIZEOF_VALUE]; @@ -2983,6 +2983,14 @@ warn_unused_block(const rb_callable_method_entry_t *cme, const rb_iseq_t *iseq, .v = (VALUE)cme->def, }; + // relax check + st_data_t key = (st_data_t)cme->def->original_id; + + if (st_lookup(dup_check_table, key, NULL)) { + return; + } + + // strict check // make unique key from pc and me->def pointer for (int i=0; i Date: Wed, 17 Apr 2024 12:51:27 +0100 Subject: [PATCH 35/39] Inline single use variables --- gc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/gc.c b/gc.c index acf81ef1301844..1f5d0fe365494b 100644 --- a/gc.c +++ b/gc.c @@ -9125,10 +9125,7 @@ gc_start(rb_objspace_t *objspace, unsigned int reason) static void gc_rest(rb_objspace_t *objspace) { - int marking = is_incremental_marking(objspace); - int sweeping = is_lazy_sweeping(objspace); - - if (marking || sweeping) { + if (is_incremental_marking(objspace) || is_lazy_sweeping(objspace)) { unsigned int lock_lev; gc_enter(objspace, gc_enter_event_rest, &lock_lev); From 209e2f277e5d528a8bbbccbb5fac6ca087ed2335 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 16 Apr 2024 14:06:36 -0400 Subject: [PATCH 36/39] Don't allow T_NIL in gc_is_moveable_obj gc_is_moveable_obj is only given GC managed objects, and T_NIL cannot be a GC managed type. --- gc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/gc.c b/gc.c index 1f5d0fe365494b..044ce2c98488df 100644 --- a/gc.c +++ b/gc.c @@ -9511,7 +9511,6 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj) switch (BUILTIN_TYPE(obj)) { case T_NONE: - case T_NIL: case T_MOVED: case T_ZOMBIE: return FALSE; From f72436f8355dd19298b3f7d25d6c23cb75b3a02a Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 16 Apr 2024 10:30:50 -0400 Subject: [PATCH 37/39] [ruby/prism] Inline pm_state_stack --- lib/prism/prism.gemspec | 2 -- prism/parser.h | 6 +++++- prism/prism.c | 24 +++++++++++++++++++++ prism/util/pm_state_stack.c | 25 ---------------------- prism/util/pm_state_stack.h | 42 ------------------------------------- 5 files changed, 29 insertions(+), 70 deletions(-) delete mode 100644 prism/util/pm_state_stack.c delete mode 100644 prism/util/pm_state_stack.h diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index 6cf28460c2d5af..f4be1b36bbffb2 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -63,7 +63,6 @@ Gem::Specification.new do |spec| "include/prism/util/pm_list.h", "include/prism/util/pm_memchr.h", "include/prism/util/pm_newline_list.h", - "include/prism/util/pm_state_stack.h", "include/prism/util/pm_strncasecmp.h", "include/prism/util/pm_string.h", "include/prism/util/pm_string_list.h", @@ -117,7 +116,6 @@ Gem::Specification.new do |spec| "src/util/pm_list.c", "src/util/pm_memchr.c", "src/util/pm_newline_list.c", - "src/util/pm_state_stack.c", "src/util/pm_string.c", "src/util/pm_string_list.c", "src/util/pm_strncasecmp.c", diff --git a/prism/parser.h b/prism/parser.h index b0ff2f38fcf38d..b35026e6a25900 100644 --- a/prism/parser.h +++ b/prism/parser.h @@ -13,7 +13,6 @@ #include "prism/util/pm_constant_pool.h" #include "prism/util/pm_list.h" #include "prism/util/pm_newline_list.h" -#include "prism/util/pm_state_stack.h" #include "prism/util/pm_string.h" #include @@ -612,6 +611,11 @@ static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_ALL = 0x40; static const int8_t PM_SCOPE_NUMBERED_PARAMETERS_DISALLOWED = -1; static const int8_t PM_SCOPE_NUMBERED_PARAMETERS_NONE = 0; +/** + * A struct that represents a stack of boolean values. + */ +typedef uint32_t pm_state_stack_t; + /** * This struct represents the overall parser. It contains a reference to the * source file, as well as pointers that indicate where in the source it's diff --git a/prism/prism.c b/prism/prism.c index 9c489e478567bf..18675b994a9c24 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -7632,6 +7632,30 @@ pm_parser_scope_pop(pm_parser_t *parser) { /* Stack helpers */ /******************************************************************************/ +/** + * Pushes a value onto the stack. + */ +static inline void +pm_state_stack_push(pm_state_stack_t *stack, bool value) { + *stack = (*stack << 1) | (value & 1); +} + +/** + * Pops a value off the stack. + */ +static inline void +pm_state_stack_pop(pm_state_stack_t *stack) { + *stack >>= 1; +} + +/** + * Returns the value at the top of the stack. + */ +static inline bool +pm_state_stack_p(const pm_state_stack_t *stack) { + return *stack & 1; +} + static inline void pm_accepts_block_stack_push(pm_parser_t *parser, bool value) { // Use the negation of the value to prevent stack overflow. diff --git a/prism/util/pm_state_stack.c b/prism/util/pm_state_stack.c deleted file mode 100644 index 2a424b4c03c296..00000000000000 --- a/prism/util/pm_state_stack.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "prism/util/pm_state_stack.h" - -/** - * Pushes a value onto the stack. - */ -void -pm_state_stack_push(pm_state_stack_t *stack, bool value) { - *stack = (*stack << 1) | (value & 1); -} - -/** - * Pops a value off the stack. - */ -void -pm_state_stack_pop(pm_state_stack_t *stack) { - *stack >>= 1; -} - -/** - * Returns the value at the top of the stack. - */ -bool -pm_state_stack_p(pm_state_stack_t *stack) { - return *stack & 1; -} diff --git a/prism/util/pm_state_stack.h b/prism/util/pm_state_stack.h deleted file mode 100644 index 1ce57a2209f0c2..00000000000000 --- a/prism/util/pm_state_stack.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file pm_state_stack.h - * - * A stack of boolean values. - */ -#ifndef PRISM_STATE_STACK_H -#define PRISM_STATE_STACK_H - -#include "prism/defines.h" - -#include -#include - -/** - * A struct that represents a stack of boolean values. - */ -typedef uint32_t pm_state_stack_t; - -/** - * Pushes a value onto the stack. - * - * @param stack The stack to push the value onto. - * @param value The value to push onto the stack. - */ -void pm_state_stack_push(pm_state_stack_t *stack, bool value); - -/** - * Pops a value off the stack. - * - * @param stack The stack to pop the value off of. - */ -void pm_state_stack_pop(pm_state_stack_t *stack); - -/** - * Returns the value at the top of the stack. - * - * @param stack The stack to get the value from. - * @return The value at the top of the stack. - */ -bool pm_state_stack_p(pm_state_stack_t *stack); - -#endif From 8c8068c06fd149659bd1d42315f8206b91defdf9 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 17 Apr 2024 10:02:05 -0400 Subject: [PATCH 38/39] [PRISM] Remove old make targets for state stack --- common.mk | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/common.mk b/common.mk index c2b24674668e95..b0f85a5da5e9ad 100644 --- a/common.mk +++ b/common.mk @@ -105,7 +105,6 @@ PRISM_FILES = prism/api_node.$(OBJEXT) \ prism/util/pm_list.$(OBJEXT) \ prism/util/pm_memchr.$(OBJEXT) \ prism/util/pm_newline_list.$(OBJEXT) \ - prism/util/pm_state_stack.$(OBJEXT) \ prism/util/pm_string.$(OBJEXT) \ prism/util/pm_string_list.$(OBJEXT) \ prism/util/pm_strncasecmp.$(OBJEXT) \ @@ -2267,7 +2266,6 @@ ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -2704,7 +2702,6 @@ builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -3339,7 +3336,6 @@ compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -3804,7 +3800,6 @@ cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -6779,7 +6774,6 @@ eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -7260,7 +7254,6 @@ gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -7517,7 +7510,6 @@ goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -7761,7 +7753,6 @@ hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -8800,7 +8791,6 @@ iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -9057,7 +9047,6 @@ load.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -load.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -10388,7 +10377,6 @@ miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -11976,7 +11964,6 @@ prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -12172,7 +12159,6 @@ prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -12382,7 +12368,6 @@ prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -12570,7 +12555,6 @@ prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -12596,7 +12580,6 @@ prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/prettyprint.$(OBJEXT): {$(VPATH)}prism/ast.h @@ -12619,7 +12602,6 @@ prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -12641,7 +12623,6 @@ prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -12663,7 +12644,6 @@ prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -12685,7 +12665,6 @@ prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/static_literals.$(OBJEXT): {$(VPATH)}prism/ast.h @@ -12727,16 +12706,12 @@ prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.c prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/util/pm_memchr.$(OBJEXT): {$(VPATH)}prism/ast.h prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.c prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -prism/util/pm_state_stack.$(OBJEXT): $(top_srcdir)/prism/defines.h -prism/util/pm_state_stack.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.c -prism/util/pm_state_stack.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.c prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h @@ -12757,7 +12732,6 @@ prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.c @@ -12784,7 +12758,6 @@ prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -13001,7 +12974,6 @@ proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -15485,7 +15457,6 @@ rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -15739,7 +15710,6 @@ rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -16019,7 +15989,6 @@ ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -18461,7 +18430,6 @@ thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -19723,7 +19691,6 @@ vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -19982,7 +19949,6 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -20213,7 +20179,6 @@ vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -20655,7 +20620,6 @@ vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h @@ -21097,7 +21061,6 @@ yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h -yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h From 15b659ca932254102ee3706aefa7a04d5c43969e Mon Sep 17 00:00:00 2001 From: tomoya ishida Date: Thu, 18 Apr 2024 01:12:14 +0900 Subject: [PATCH 39/39] [ruby/reline] Refactor nomultiline and multiline mode difference (https://github.com/ruby/reline/pull/653) * Support multiline input in Reline.readline internally, reduce multiline-singleline branch * Add readline(singleline) prompt test with force inserting multiline text https://github.com/ruby/reline/commit/97846095d7 --- lib/reline/line_editor.rb | 146 ++++++++------------ test/reline/helper.rb | 2 +- test/reline/yamatanooroti/test_rendering.rb | 15 ++ 3 files changed, 71 insertions(+), 92 deletions(-) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index c84a78a06cc94f..6e5ef11bc000d1 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -112,7 +112,11 @@ def set_pasting_state(in_pasting) else prompt = @prompt end - if @prompt_proc + if !@is_multiline + mode_string = check_mode_string + prompt = mode_string + prompt if mode_string + [prompt] + [''] * (buffer.size - 1) + elsif @prompt_proc prompt_list = @prompt_proc.(buffer).map { |pr| pr.gsub("\n", "\\n") } prompt_list.map!{ prompt } if @vi_arg or @searching_prompt prompt_list = [prompt] if prompt_list.empty? @@ -1220,7 +1224,7 @@ def call_completion_proc_with_checking_args(pre, target, post) end def line() - current_line unless eof? + @buffer_of_lines.join("\n") unless eof? end def current_line @@ -1304,14 +1308,12 @@ def retrieve_completion_block(set_completion_quote_character = false) end target = before end - if @is_multiline - lines = whole_lines - if @line_index > 0 - preposing = lines[0..(@line_index - 1)].join("\n") + "\n" + preposing - end - if (lines.size - 1) > @line_index - postposing = postposing + "\n" + lines[(@line_index + 1)..-1].join("\n") - end + lines = whole_lines + if @line_index > 0 + preposing = lines[0..(@line_index - 1)].join("\n") + "\n" + preposing + end + if (lines.size - 1) > @line_index + postposing = postposing + "\n" + lines[(@line_index + 1)..-1].join("\n") end [preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)] end @@ -1333,20 +1335,16 @@ def insert_text(text) def delete_text(start = nil, length = nil) if start.nil? and length.nil? - if @is_multiline - if @buffer_of_lines.size == 1 - @buffer_of_lines[@line_index] = '' - @byte_pointer = 0 - elsif @line_index == (@buffer_of_lines.size - 1) and @line_index > 0 - @buffer_of_lines.pop - @line_index -= 1 - @byte_pointer = 0 - elsif @line_index < (@buffer_of_lines.size - 1) - @buffer_of_lines.delete_at(@line_index) - @byte_pointer = 0 - end - else - set_current_line('', 0) + if @buffer_of_lines.size == 1 + @buffer_of_lines[@line_index] = '' + @byte_pointer = 0 + elsif @line_index == (@buffer_of_lines.size - 1) and @line_index > 0 + @buffer_of_lines.pop + @line_index -= 1 + @byte_pointer = 0 + elsif @line_index < (@buffer_of_lines.size - 1) + @buffer_of_lines.delete_at(@line_index) + @byte_pointer = 0 end elsif not start.nil? and not length.nil? if current_line @@ -1502,7 +1500,7 @@ def finish byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer) if (@byte_pointer < current_line.bytesize) @byte_pointer += byte_size - elsif @is_multiline and @config.editing_mode_is?(:emacs) and @byte_pointer == current_line.bytesize and @line_index < @buffer_of_lines.size - 1 + elsif @config.editing_mode_is?(:emacs) and @byte_pointer == current_line.bytesize and @line_index < @buffer_of_lines.size - 1 @byte_pointer = 0 @line_index += 1 end @@ -1515,7 +1513,7 @@ def finish if @byte_pointer > 0 byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer) @byte_pointer -= byte_size - elsif @is_multiline and @config.editing_mode_is?(:emacs) and @byte_pointer == 0 and @line_index > 0 + elsif @config.editing_mode_is?(:emacs) and @byte_pointer == 0 and @line_index > 0 @line_index -= 1 @byte_pointer = current_line.bytesize end @@ -1546,7 +1544,6 @@ def finish private def generate_searcher(search_key) search_word = String.new(encoding: @encoding) multibyte_buf = String.new(encoding: 'ASCII-8BIT') - last_hit = nil hit_pointer = nil lambda do |key| search_again = false @@ -1624,18 +1621,13 @@ def finish prompt_name = 'i-search' end prompt_name = "failed #{prompt_name}" unless hit - last_hit = hit if hit_pointer - [search_word, prompt_name, hit_pointer, hit, last_hit] + [search_word, prompt_name, hit_pointer] end end private def incremental_search_history(key) unless @history_pointer - if @is_multiline - @line_backup_in_history = whole_buffer - else - @line_backup_in_history = current_line - end + @line_backup_in_history = whole_buffer end searcher = generate_searcher(key) @searching_prompt = "(reverse-i-search)`': " @@ -1649,24 +1641,16 @@ def finish else buffer = @line_backup_in_history end - if @is_multiline - @buffer_of_lines = buffer.split("\n") - @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? - @line_index = @buffer_of_lines.size - 1 - else - @buffer_of_lines = [buffer] - end + @buffer_of_lines = buffer.split("\n") + @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? + @line_index = @buffer_of_lines.size - 1 @searching_prompt = nil @waiting_proc = nil @byte_pointer = 0 when "\C-g".ord - if @is_multiline - @buffer_of_lines = @line_backup_in_history.split("\n") - @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? - @line_index = @buffer_of_lines.size - 1 - else - @buffer_of_lines = [@line_backup_in_history] - end + @buffer_of_lines = @line_backup_in_history.split("\n") + @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? + @line_index = @buffer_of_lines.size - 1 move_history(nil, line: :end, cursor: :end, save_buffer: false) @searching_prompt = nil @waiting_proc = nil @@ -1674,13 +1658,10 @@ def finish else chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT) if chr.match?(/[[:print:]]/) or k == "\C-h".ord or k == "\C-?".ord or k == "\C-r".ord or k == "\C-s".ord - search_word, prompt_name, hit_pointer, hit, last_hit = searcher.call(k) + search_word, prompt_name, hit_pointer = searcher.call(k) Reline.last_incremental_search = search_word - if @is_multiline - @searching_prompt = "(%s)`%s'" % [prompt_name, search_word] - else - @searching_prompt = "(%s)`%s': %s" % [prompt_name, search_word, hit || last_hit] - end + @searching_prompt = "(%s)`%s'" % [prompt_name, search_word] + @searching_prompt += ': ' unless @is_multiline move_history(hit_pointer, line: :end, cursor: :end, save_buffer: false) if hit_pointer else if @history_pointer @@ -1688,15 +1669,10 @@ def finish else line = @line_backup_in_history end - if @is_multiline - @line_backup_in_history = whole_buffer - @buffer_of_lines = line.split("\n") - @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? - @line_index = @buffer_of_lines.size - 1 - else - @line_backup_in_history = current_line - @buffer_of_lines = [line] - end + @line_backup_in_history = whole_buffer + @buffer_of_lines = line.split("\n") + @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? + @line_index = @buffer_of_lines.size - 1 @searching_prompt = nil @waiting_proc = nil @byte_pointer = 0 @@ -1770,18 +1746,14 @@ def finish buf = Reline::HISTORY[history_pointer] @history_pointer = history_pointer end - if @is_multiline - @buffer_of_lines = buf.split("\n") - @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? - @line_index = line == :start ? 0 : line == :end ? @buffer_of_lines.size - 1 : line - else - @buffer_of_lines = [buf] - end + @buffer_of_lines = buf.split("\n") + @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? + @line_index = line == :start ? 0 : line == :end ? @buffer_of_lines.size - 1 : line @byte_pointer = cursor == :start ? 0 : cursor == :end ? current_line.bytesize : cursor end private def ed_prev_history(key, arg: 1) - if @is_multiline and @line_index > 0 + if @line_index > 0 cursor = current_byte_pointer_cursor @line_index -= 1 calculate_nearest_cursor(cursor) @@ -1798,7 +1770,7 @@ def finish alias_method :previous_history, :ed_prev_history private def ed_next_history(key, arg: 1) - if @is_multiline and @line_index < (@buffer_of_lines.size - 1) + if @line_index < (@buffer_of_lines.size - 1) cursor = current_byte_pointer_cursor @line_index += 1 calculate_nearest_cursor(cursor) @@ -1845,7 +1817,7 @@ def finish private def em_delete_prev_char(key, arg: 1) arg.times do - if @is_multiline and @byte_pointer == 0 and @line_index > 0 + if @byte_pointer == 0 and @line_index > 0 @byte_pointer = @buffer_of_lines[@line_index - 1].bytesize @buffer_of_lines[@line_index - 1] += @buffer_of_lines.delete_at(@line_index) @line_index -= 1 @@ -1869,7 +1841,7 @@ def finish line, deleted = byteslice!(current_line, @byte_pointer, current_line.bytesize - @byte_pointer) set_current_line(line, line.bytesize) @kill_ring.append(deleted) - elsif @is_multiline and @byte_pointer == current_line.bytesize and @buffer_of_lines.size > @line_index + 1 + elsif @byte_pointer == current_line.bytesize and @buffer_of_lines.size > @line_index + 1 set_current_line(current_line + @buffer_of_lines.delete_at(@line_index + 1), current_line.bytesize) end end @@ -1909,7 +1881,7 @@ def finish alias_method :kill_whole_line, :em_kill_line private def em_delete(key) - if current_line.empty? and (not @is_multiline or @buffer_of_lines.size == 1) and key == "\C-d".ord + if current_line.empty? and @buffer_of_lines.size == 1 and key == "\C-d".ord @eof = true finish elsif @byte_pointer < current_line.bytesize @@ -1917,7 +1889,7 @@ def finish mbchar = splitted_last.grapheme_clusters.first line, = byteslice!(current_line, @byte_pointer, mbchar.bytesize) set_current_line(line) - elsif @is_multiline and @byte_pointer == current_line.bytesize and @buffer_of_lines.size > @line_index + 1 + elsif @byte_pointer == current_line.bytesize and @buffer_of_lines.size > @line_index + 1 set_current_line(current_line + @buffer_of_lines.delete_at(@line_index + 1), current_line.bytesize) end end @@ -2160,7 +2132,7 @@ def finish end private def vi_delete_prev_char(key) - if @is_multiline and @byte_pointer == 0 and @line_index > 0 + if @byte_pointer == 0 and @line_index > 0 @byte_pointer = @buffer_of_lines[@line_index - 1].bytesize @buffer_of_lines[@line_index - 1] += @buffer_of_lines.delete_at(@line_index) @line_index -= 1 @@ -2257,7 +2229,7 @@ def finish end private def vi_list_or_eof(key) - if (not @is_multiline and current_line.empty?) or (@is_multiline and current_line.empty? and @buffer_of_lines.size == 1) + if current_line.empty? and @buffer_of_lines.size == 1 set_current_line('', 0) @eof = true finish @@ -2293,21 +2265,13 @@ def finish private def vi_histedit(key) path = Tempfile.open { |fp| - if @is_multiline - fp.write whole_lines.join("\n") - else - fp.write current_line - end + fp.write whole_lines.join("\n") fp.path } system("#{ENV['EDITOR']} #{path}") - if @is_multiline - @buffer_of_lines = File.read(path).split("\n") - @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? - @line_index = 0 - else - @buffer_of_lines = File.read(path).split("\n") - end + @buffer_of_lines = File.read(path).split("\n") + @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? + @line_index = 0 finish end @@ -2479,7 +2443,7 @@ def finish end private def vi_join_lines(key, arg: 1) - if @is_multiline and @buffer_of_lines.size > @line_index + 1 + if @buffer_of_lines.size > @line_index + 1 next_line = @buffer_of_lines.delete_at(@line_index + 1).lstrip set_current_line(current_line + ' ' + next_line, current_line.bytesize) end diff --git a/test/reline/helper.rb b/test/reline/helper.rb index f2f3421ded0bf4..26fe8344829523 100644 --- a/test/reline/helper.rb +++ b/test/reline/helper.rb @@ -131,7 +131,7 @@ def input_raw_keys(input, convert = true) def assert_line_around_cursor(before, after) before = convert_str(before) after = convert_str(after) - line = @line_editor.line + line = @line_editor.current_line byte_pointer = @line_editor.instance_variable_get(:@byte_pointer) actual_before = line.byteslice(0, byte_pointer) actual_after = line.byteslice(byte_pointer..) diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb index fe0f8842eafa92..09d064934a9c32 100644 --- a/test/reline/yamatanooroti/test_rendering.rb +++ b/test/reline/yamatanooroti/test_rendering.rb @@ -309,6 +309,21 @@ def test_prompt_with_escape_sequence_and_autowrap EOC end + def test_readline_with_multiline_input + start_terminal(5, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dynamic-prompt}, startup_message: 'Multiline REPL.') + write("def foo\n bar\nend\n") + write("Reline.readline('prompt> ')\n") + write("\C-p\C-p") + close + assert_screen(<<~EOC) + => :foo + [0000]> Reline.readline('prompt> ') + prompt> def foo + bar + end + EOC + end + def test_multiline_and_autowrap start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') write("def aaaaaaaaaa\n 33333333\n end\C-a\C-pputs\C-e\e\C-m888888888888888")