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/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/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/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 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 diff --git a/NEWS.md b/NEWS.md index 34fa51ce9d051a..f3368421a9a10e 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. @@ -47,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 @@ -118,11 +122,17 @@ 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 [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 diff --git a/class.c b/class.c index ada95dde1a57d5..36736a6091dcff 100644 --- a/class.c +++ b/class.c @@ -2335,7 +2335,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/common.mk b/common.mk index 3fce9df761bf80..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) \ @@ -337,7 +336,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 +478,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) @@ -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 diff --git a/compile.c b/compile.c index 791620aaa25578..2a4eb70122d912 100644 --- a/compile.c +++ b/compile.c @@ -1999,6 +1999,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) { @@ -2100,7 +2113,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); @@ -5921,7 +5934,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: @@ -8637,7 +8650,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; @@ -9486,7 +9499,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; @@ -9532,7 +9545,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); @@ -10014,7 +10027,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; @@ -11766,6 +11779,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/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/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/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) 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. 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/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: 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/gc.c b/gc.c index 6655d62fa89855..bf4d9166b6e52d 100644 --- a/gc.c +++ b/gc.c @@ -7415,10 +7415,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 @@ -12074,13 +12071,9 @@ 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)) { LOCAL_GC_BEGIN(objspace); { - gc_enter(objspace, gc_enter_event_rest); if (RGENGC_CHECK_MODE >= 2) gc_verify_internal_consistency(objspace); @@ -12572,12 +12565,11 @@ 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; 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 */ 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/iseq.c b/iseq.c index 7b3fc1a3743d7e..9bc8fb6c61cbcc 100644 --- a/iseq.c +++ b/iseq.c @@ -3204,6 +3204,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/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/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/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index e4d7ecf1a29189..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 @@ -1543,131 +1541,95 @@ 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') + 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 + [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 - 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 @@ -1679,53 +1641,41 @@ 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 - searcher.resume(-1) 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 - @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 = @buffer_of_lines.size - 1 + 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 = searcher.call(k) + Reline.last_incremental_search = search_word + @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 line = Reline::HISTORY[@history_pointer] 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 - searcher.resume(-1) end end } @@ -1741,191 +1691,96 @@ 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? - } - else - h_pointer = history.index { |l| - l.start_with?(substr) - } - end - h_pointer += @history_pointer + 1 if h_pointer and @history_pointer + h_pointer, line_index = search_history(substr, history_range) 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 = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? - else - if @history_pointer.nil? and substr.empty? - set_current_line('', 0) - else - set_current_line(Reline::HISTORY[@history_pointer]) - end - end + + 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 + 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 + @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) 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 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) 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,17 +1811,13 @@ def finish end end else - if @history_pointer - Reline::HISTORY[@history_pointer] = whole_buffer - @history_pointer = nil - end finish end end 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 @@ -1990,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 @@ -2030,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 @@ -2038,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 @@ -2281,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 @@ -2378,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 @@ -2409,36 +2260,18 @@ 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) 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 @@ -2610,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 @@ -2630,4 +2463,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/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 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/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/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/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 91d27f566d4e00..18675b994a9c24 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; } @@ -7631,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. @@ -12945,6 +12970,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 +19408,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; } } @@ -21191,6 +21254,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/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 }, diff --git a/prism/util/pm_integer.c b/prism/util/pm_integer.c index 8f8b75474df33a..0739662e98037b 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; @@ -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; @@ -326,6 +330,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 +351,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 +590,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) { 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 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/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/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 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/string.c b/string.c index 98bf0dcbb82d11..b760c4652cc410 100644 --- a/string.c +++ b/string.c @@ -380,7 +380,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)) { @@ -416,7 +416,7 @@ rb_fstring(VALUE str) bare = BARE_STRING_P(str); if (!bare) { if (STR_EMBED_P(str)) { - OBJ_FREEZE_RAW(str); + OBJ_FREEZE(str); FL_SET_RAW(str, RUBY_FL_SHAREABLE); return str; } @@ -437,7 +437,7 @@ rb_fstring(VALUE str) if (!bare) { str_replace_shared_without_enc(str, fstr); - OBJ_FREEZE_RAW(str); + OBJ_FREEZE(str); FL_SET_RAW(str, RUBY_FL_SHAREABLE); return str; } 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/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/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 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") 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/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) diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb index dc84d8bd7c4b51..dbf91fe8c94025 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -827,6 +827,24 @@ def test_compile_prism_with_file end end + def block_using_method + yield + end + + def block_unused_method + end + + def test_unused_param + 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 assert_raise(TypeError) do RubyVM::InstructionSequence.compile_prism(Object.new) 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/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 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) 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" 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" 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 diff --git a/thread.c b/thread.c index 404c009a13c78c..b4edc845670746 100644 --- a/thread.c +++ b/thread.c @@ -2300,7 +2300,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); @@ -5864,7 +5864,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/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 diff --git a/variable.c b/variable.c index 2478d65db2b5b4..983cd76be2e67d 100644 --- a/variable.c +++ b/variable.c @@ -1874,7 +1874,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); diff --git a/vm.c b/vm.c index 329e47fe68de94..e6fa34f61692e7 100644 --- a/vm.c +++ b/vm.c @@ -4300,6 +4300,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(); rb_native_mutex_initialize(&vm->subclass_list_lock); vm->subclass_list_lock_owner = NULL; 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); } 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 */ diff --git a/vm_core.h b/vm_core.h index 949d912872a1dd..6395ebf759e9cd 100644 --- a/vm_core.h +++ b/vm_core.h @@ -796,6 +796,7 @@ typedef struct rb_vm_struct { 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 04e7d3714ef288..ccf93fa6b553a4 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -2980,9 +2980,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]; @@ -2992,6 +2992,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; idefined_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 { 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; }