From 99929d6f2b8433d5d2573054f08070e8a4c6bac3 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 Oct 2025 09:20:03 -0400 Subject: [PATCH 1/7] [ruby/prism] Do not rely on Gem being loaded https://github.com/ruby/prism/commit/2466940e49 --- lib/prism.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/prism.rb b/lib/prism.rb index 2cbe196b57e2b4..bae5427e79dee3 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -42,13 +42,12 @@ class CurrentVersionError < ArgumentError # Initialize a new exception for the given ruby version string. def initialize(version) message = +"invalid version: Requested to parse as `version: 'current'`; " - gem_version = - begin - Gem::Version.new(version) - rescue ArgumentError + segments = + if version.match?(/\A\d+\.\d+.\d+\z/) + version.split(".").map(&:to_i) end - if gem_version && gem_version < Gem::Version.new("3.3.0") + if segments && (segments[0] < 3) || (segments[0] == 3 && segments[1] < 3) message << " #{version} is below the minimum supported syntax." else message << " #{version} is unknown. Please update the `prism` gem." From 6652d5072fa4888443d43db0a4026524b56925bf Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 Oct 2025 09:59:47 -0400 Subject: [PATCH 2/7] [ruby/prism] Create a new string for the current version error https://github.com/ruby/prism/commit/ebf4425d49 --- prism/extension.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/prism/extension.c b/prism/extension.c index 0c9d04225da1fe..71c2d91b98d0f0 100644 --- a/prism/extension.c +++ b/prism/extension.c @@ -201,10 +201,9 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { const char *version = check_string(value); if (RSTRING_LEN(value) == 7 && strncmp(version, "current", 7) == 0) { - VALUE current_ruby_value = rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")); - const char *current_version = RSTRING_PTR(current_ruby_value); + const char *current_version = RSTRING_PTR(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION"))); if (!pm_options_version_set(options, current_version, 3)) { - rb_exc_raise(rb_exc_new_str(rb_cPrismCurrentVersionError, current_ruby_value)); + rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, current_version)); } } else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) { rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value); From cea3307fe61992f576dd665ae1066e8073b53dab Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 Oct 2025 10:10:02 -0400 Subject: [PATCH 3/7] [ruby/prism] Do not stub Ruby version https://github.com/ruby/prism/commit/44c4306247 --- test/prism/api/parse_test.rb | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/test/prism/api/parse_test.rb b/test/prism/api/parse_test.rb index 67a252c5895541..96aec7c838457a 100644 --- a/test/prism/api/parse_test.rb +++ b/test/prism/api/parse_test.rb @@ -148,15 +148,8 @@ def test_version_current end version = RUBY_VERSION.split(".").tap { |segments| segments[0] = segments[0].succ }.join(".") - stub_ruby_version(version) do - error = assert_raise(CurrentVersionError) { Prism.parse("1 + 1", version: "current") } - assert_includes error.message, "unknown" - end - - stub_ruby_version("2.7.0") do - error = assert_raise(CurrentVersionError) { Prism.parse("1 + 1", version: "current") } - assert_includes error.message, "minimum" - end + assert_includes CurrentVersionError.new(version).message, "unknown" + assert_includes CurrentVersionError.new("2.7").message, "minimum" end def test_scopes @@ -186,16 +179,5 @@ def find_source_file_node(program) queue.concat(node.compact_child_nodes) end end - - def stub_ruby_version(version) - old_version = RUBY_VERSION - - Object.send(:remove_const, :RUBY_VERSION) - Object.const_set(:RUBY_VERSION, version) - yield - ensure - Object.send(:remove_const, :RUBY_VERSION) - Object.const_set(:RUBY_VERSION, old_version) - end end end From a8a8f1c20e3f10614de7b6bc262d910678b4f526 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 Oct 2025 10:29:11 -0400 Subject: [PATCH 4/7] [ruby/prism] Handle RUBY_VERSION being nil https://github.com/ruby/prism/commit/dda0dc81df --- lib/prism.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/prism.rb b/lib/prism.rb index bae5427e79dee3..f6ad0c1fd10155 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -47,7 +47,7 @@ def initialize(version) version.split(".").map(&:to_i) end - if segments && (segments[0] < 3) || (segments[0] == 3 && segments[1] < 3) + if segments && ((segments[0] < 3) || (segments[0] == 3 && segments[1] < 3)) message << " #{version} is below the minimum supported syntax." else message << " #{version} is unknown. Please update the `prism` gem." From 68f45a6da7bcea9126e04653a5ab47ddcb3b3126 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 Oct 2025 10:37:42 -0400 Subject: [PATCH 5/7] [ruby/prism] Do not rely on RUBY_VERSION being consistent https://github.com/ruby/prism/commit/34428946db --- test/prism/api/parse_test.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/prism/api/parse_test.rb b/test/prism/api/parse_test.rb index 96aec7c838457a..1f885fa4935302 100644 --- a/test/prism/api/parse_test.rb +++ b/test/prism/api/parse_test.rb @@ -146,10 +146,6 @@ def test_version_current else assert_raise(CurrentVersionError) { Prism.parse_success?("1 + 1", version: "current") } end - - version = RUBY_VERSION.split(".").tap { |segments| segments[0] = segments[0].succ }.join(".") - assert_includes CurrentVersionError.new(version).message, "unknown" - assert_includes CurrentVersionError.new("2.7").message, "minimum" end def test_scopes From f925f1ae7b18c6314fe59d19cd56107de91c3b26 Mon Sep 17 00:00:00 2001 From: Max Bernstein Date: Thu, 16 Oct 2025 11:34:07 -0400 Subject: [PATCH 6/7] ZJIT: Inline BasicObject#initialize (#14856) It just returns nil. --- zjit/src/cruby_methods.rs | 8 +++++++- zjit/src/hir.rs | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/zjit/src/cruby_methods.rs b/zjit/src/cruby_methods.rs index 11496f7b9874a0..ea9f1beffce3f8 100644 --- a/zjit/src/cruby_methods.rs +++ b/zjit/src/cruby_methods.rs @@ -205,7 +205,7 @@ pub fn init() -> Annotations { annotate!(rb_mKernel, "nil?", types::FalseClass, no_gc, leaf, elidable); annotate!(rb_cBasicObject, "==", types::BoolExact, no_gc, leaf, elidable); annotate!(rb_cBasicObject, "!", types::BoolExact, no_gc, leaf, elidable); - annotate!(rb_cBasicObject, "initialize", types::NilClass, no_gc, leaf, elidable); + annotate!(rb_cBasicObject, "initialize", inline_basic_object_initialize); annotate!(rb_cInteger, "succ", inline_integer_succ); annotate!(rb_cString, "to_s", inline_string_to_s); let thread_singleton = unsafe { rb_singleton_class(rb_cThread) }; @@ -282,3 +282,9 @@ fn inline_integer_succ(fun: &mut hir::Function, block: hir::BlockId, recv: hir:: } None } + +fn inline_basic_object_initialize(fun: &mut hir::Function, block: hir::BlockId, _recv: hir::InsnId, args: &[hir::InsnId], _state: hir::InsnId) -> Option { + if !args.is_empty() { return None; } + let result = fun.push_insn(block, hir::Insn::Const { val: hir::Const::Value(Qnil) }); + Some(result) +} diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index a87a416e9e5408..633e4d64f7b024 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -10626,7 +10626,7 @@ mod opt_tests { v43:HeapObject[class_exact:C] = ObjectAllocClass C:VALUE(0x1008) PatchPoint MethodRedefined(C@0x1008, initialize@0x1040, cme:0x1048) PatchPoint NoSingletonClass(C@0x1008) - v47:NilClass = CCall initialize@0x1070, v43 + v47:NilClass = Const Value(nil) CheckInterrupts CheckInterrupts Return v43 @@ -10694,7 +10694,7 @@ mod opt_tests { v43:ObjectExact = ObjectAllocClass Object:VALUE(0x1008) PatchPoint MethodRedefined(Object@0x1008, initialize@0x1040, cme:0x1048) PatchPoint NoSingletonClass(Object@0x1008) - v47:NilClass = CCall initialize@0x1070, v43 + v47:NilClass = Const Value(nil) CheckInterrupts CheckInterrupts Return v43 @@ -10725,7 +10725,7 @@ mod opt_tests { v43:BasicObjectExact = ObjectAllocClass BasicObject:VALUE(0x1008) PatchPoint MethodRedefined(BasicObject@0x1008, initialize@0x1040, cme:0x1048) PatchPoint NoSingletonClass(BasicObject@0x1008) - v47:NilClass = CCall initialize@0x1070, v43 + v47:NilClass = Const Value(nil) CheckInterrupts CheckInterrupts Return v43 From 190a3cd4759e62166004639bbe3b1f6a134b1f3b Mon Sep 17 00:00:00 2001 From: Aiden Fox Ivey Date: Thu, 16 Oct 2025 13:35:33 -0400 Subject: [PATCH 7/7] ZJIT: [DOC] Recommend cargo-binstall for ZJIT tool installation (GH-14859) --- doc/zjit.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/zjit.md b/doc/zjit.md index d0d3e361913039..f3db94448d4513 100644 --- a/doc/zjit.md +++ b/doc/zjit.md @@ -32,11 +32,17 @@ Note that tests link against CRuby, so directly calling `cargo test`, or `cargo First, ensure you have `cargo` installed. If you do not already have it, you can use [rustup.rs](https://rustup.rs/). +Also install cargo-binstall with: + +```bash +cargo install cargo-binstall +``` + Make sure to add `--enable-zjit=dev` when you run `configure`, then install the following tools: ```bash -cargo install cargo-nextest -cargo install cargo-insta +cargo binstall --secure cargo-nextest +cargo binstall --secure cargo-insta ``` `cargo-insta` is used for updating snapshots. `cargo-nextest` runs each test in its own process, which is valuable since CRuby only supports booting once per process, and most APIs are not thread safe.