diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb index 2428a401cf..ce51dd83f7 100644 --- a/test/ruby/test_yjit.rb +++ b/test/ruby/test_yjit.rb @@ -1119,6 +1119,23 @@ class TestYJIT < Test::Unit::TestCase RUBY end + def test_str_uplus_subclass + assert_compiles(<<~RUBY, frozen_string_literal: true, result: :subclass) + class S < String + def encoding + :subclass + end + end + + def test(str) + (+str).encoding + end + + test "" + test S.new + RUBY + end + private def code_gc_helpers diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index be8a5ee4b9..f2294db13f 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -4164,10 +4164,14 @@ fn jit_rb_str_uplus( _ci: *const rb_callinfo, _cme: *const rb_callable_method_entry_t, _block: Option, - _argc: i32, + argc: i32, _known_recv_class: *const VALUE, ) -> bool { + if argc != 0 { + return false; + } + // We allocate when we dup the string jit_prepare_routine_call(jit, ctx, asm); @@ -4178,8 +4182,8 @@ fn jit_rb_str_uplus( let ret_label = asm.new_label("stack_ret"); - // We guard for the receiver being a ::String, so the return value is too - let stack_ret = ctx.stack_push(Type::CString); + // String#+@ can only exist on T_STRING + let stack_ret = ctx.stack_push(Type::TString); // If the string isn't frozen, we just return it. asm.mov(stack_ret, recv_opnd);