diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index 22471d2085fa69..d519c96cd6d313 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -74,6 +74,10 @@ # include #endif +#if OSSL_OPENSSL_PREREQ(3, 0, 0) +# define OSSL_HAVE_IMMUTABLE_PKEY +#endif + /* * Common Module */ diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 0fed03332fc31e..37c132ef2ea680 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -508,7 +508,7 @@ ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self) void ossl_pkey_check_public_key(const EVP_PKEY *pkey) { -#if OSSL_OPENSSL_PREREQ(3, 0, 0) +#ifdef OSSL_HAVE_IMMUTABLE_PKEY if (EVP_PKEY_missing_parameters(pkey)) ossl_raise(ePKeyError, "parameters missing"); #else diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h index 6778381210e882..24823e0f3e721a 100644 --- a/ext/openssl/ossl_pkey.h +++ b/ext/openssl/ossl_pkey.h @@ -105,7 +105,7 @@ static VALUE ossl_##_keytype##_get_##_name(VALUE self) \ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \ _type##_get0_##_group(obj, NULL, &bn)) -#if !OSSL_OPENSSL_PREREQ(3, 0, 0) +#ifndef OSSL_HAVE_IMMUTABLE_PKEY #define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \ /* \ * call-seq: \ diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index 118d29f04fffed..77082d5c348acb 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -43,6 +43,7 @@ static VALUE eDHError; * If called without arguments, an empty instance without any parameter or key * components is created. Use #set_pqg to manually set the parameters afterwards * (and optionally #set_key to set private and public key components). + * This form is not compatible with OpenSSL 3.0 or later. * * If a String is given, tries to parse it as a DER- or PEM- encoded parameters. * See also OpenSSL::PKey.read which can parse keys of any kinds. @@ -58,14 +59,15 @@ static VALUE eDHError; * * Examples: * # Creating an instance from scratch - * # Note that this is deprecated and will not work on OpenSSL 3.0 or later. + * # Note that this is deprecated and will result in ArgumentError when + * # using OpenSSL 3.0 or later. * dh = OpenSSL::PKey::DH.new * dh.set_pqg(bn_p, nil, bn_g) * * # Generating a parameters and a key pair * dh = OpenSSL::PKey::DH.new(2048) # An alias of OpenSSL::PKey::DH.generate(2048) * - * # Reading DH parameters + * # Reading DH parameters from a PEM-encoded string * dh_params = OpenSSL::PKey::DH.new(File.read('parameters.pem')) # loads parameters only * dh = OpenSSL::PKey.generate_key(dh_params) # generates a key pair */ @@ -84,10 +86,15 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self) /* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */ if (rb_scan_args(argc, argv, "01", &arg) == 0) { +#ifdef OSSL_HAVE_IMMUTABLE_PKEY + rb_raise(rb_eArgError, "OpenSSL::PKey::DH.new cannot be called " \ + "without arguments; pkeys are immutable with OpenSSL 3.0"); +#else dh = DH_new(); if (!dh) ossl_raise(eDHError, "DH_new"); goto legacy; +#endif } arg = ossl_to_der_if_possible(arg); diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index 9f4f012cfe1686..bf92e1ceac6412 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -56,6 +56,7 @@ static VALUE eDSAError; * * If called without arguments, creates a new instance with no key components * set. They can be set individually by #set_pqg and #set_key. + * This form is not compatible with OpenSSL 3.0 or later. * * If called with a String, tries to parse as DER or PEM encoding of a \DSA key. * See also OpenSSL::PKey.read which can parse keys of any kinds. @@ -96,10 +97,15 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) /* The DSA.new(size, generator) form is handled by lib/openssl/pkey.rb */ rb_scan_args(argc, argv, "02", &arg, &pass); if (argc == 0) { +#ifdef OSSL_HAVE_IMMUTABLE_PKEY + rb_raise(rb_eArgError, "OpenSSL::PKey::DSA.new cannot be called " \ + "without arguments; pkeys are immutable with OpenSSL 3.0"); +#else dsa = DSA_new(); if (!dsa) ossl_raise(eDSAError, "DSA_new"); goto legacy; +#endif } pass = ossl_pem_passwd_value(pass); diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index 1d20f63e0c4648..e3553c44188012 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -147,9 +147,14 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "02", &arg, &pass); if (NIL_P(arg)) { +#ifdef OSSL_HAVE_IMMUTABLE_PKEY + rb_raise(rb_eArgError, "OpenSSL::PKey::EC.new cannot be called " \ + "without arguments; pkeys are immutable with OpenSSL 3.0"); +#else if (!(ec = EC_KEY_new())) ossl_raise(eECError, "EC_KEY_new"); goto legacy; +#endif } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) { ec = ec_key_new_from_group(arg); @@ -246,7 +251,7 @@ ossl_ec_key_get_group(VALUE self) static VALUE ossl_ec_key_set_group(VALUE self, VALUE group_v) { -#if OSSL_OPENSSL_PREREQ(3, 0, 0) +#ifdef OSSL_HAVE_IMMUTABLE_PKEY rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0"); #else EC_KEY *ec; @@ -288,7 +293,7 @@ static VALUE ossl_ec_key_get_private_key(VALUE self) */ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key) { -#if OSSL_OPENSSL_PREREQ(3, 0, 0) +#ifdef OSSL_HAVE_IMMUTABLE_PKEY rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0"); #else EC_KEY *ec; @@ -339,7 +344,7 @@ static VALUE ossl_ec_key_get_public_key(VALUE self) */ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key) { -#if OSSL_OPENSSL_PREREQ(3, 0, 0) +#ifdef OSSL_HAVE_IMMUTABLE_PKEY rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0"); #else EC_KEY *ec; @@ -511,7 +516,7 @@ ossl_ec_key_to_der(VALUE self) */ static VALUE ossl_ec_key_generate_key(VALUE self) { -#if OSSL_OPENSSL_PREREQ(3, 0, 0) +#ifdef OSSL_HAVE_IMMUTABLE_PKEY rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0"); #else EC_KEY *ec; @@ -1368,7 +1373,7 @@ static VALUE ossl_ec_point_make_affine(VALUE self) GetECPointGroup(self, group); rb_warn("OpenSSL::PKey::EC::Point#make_affine! is deprecated"); -#if !OSSL_OPENSSL_PREREQ(3, 0, 0) && !defined(OPENSSL_IS_AWSLC) +#if !defined(OSSL_HAVE_IMMUTABLE_PKEY) && !defined(OPENSSL_IS_AWSLC) if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1) ossl_raise(eEC_POINT, "EC_POINT_make_affine"); #endif diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index 185b47cbfb6561..4f7862023a61c7 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -59,6 +59,7 @@ static VALUE eRSAError; * If called without arguments, creates a new instance with no key components * set. They can be set individually by #set_key, #set_factors, and * #set_crt_params. + * This form is not compatible with OpenSSL 3.0 or later. * * If called with a String, tries to parse as DER or PEM encoding of an \RSA key. * Note that if _password_ is not specified, but the key is encrypted with a @@ -89,10 +90,15 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) /* The RSA.new(size, generator) form is handled by lib/openssl/pkey.rb */ rb_scan_args(argc, argv, "02", &arg, &pass); if (argc == 0) { +#ifdef OSSL_HAVE_IMMUTABLE_PKEY + rb_raise(rb_eArgError, "OpenSSL::PKey::RSA.new cannot be called " \ + "without arguments; pkeys are immutable with OpenSSL 3.0"); +#else rsa = RSA_new(); if (!rsa) ossl_raise(eRSAError, "RSA_new"); goto legacy; +#endif } pass = ossl_pem_passwd_value(pass); diff --git a/gems/bundled_gems b/gems/bundled_gems index 8de29d9937c808..d37d90bbf14eb2 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -10,7 +10,7 @@ minitest 5.25.5 https://github.com/minitest/minitest power_assert 2.0.5 https://github.com/ruby/power_assert f88e406e7c9e0810cc149869582afbae1fb84c4a rake 13.3.0 https://github.com/ruby/rake test-unit 3.7.0 https://github.com/test-unit/test-unit -rexml 3.4.2 https://github.com/ruby/rexml +rexml 3.4.4 https://github.com/ruby/rexml rss 0.3.1 https://github.com/ruby/rss net-ftp 0.3.8 https://github.com/ruby/net-ftp net-imap 0.5.10 https://github.com/ruby/net-imap 71c0288b9a8f78a7125a4ce2980ab421acdf5836 @@ -18,7 +18,7 @@ net-pop 0.1.2 https://github.com/ruby/net-pop net-smtp 0.5.1 https://github.com/ruby/net-smtp matrix 0.4.3 https://github.com/ruby/matrix prime 0.1.4 https://github.com/ruby/prime -rbs 3.9.4 https://github.com/ruby/rbs aa22d7ea0c992de7557c3e346c9100b8aa36d945 +rbs 3.9.5 https://github.com/ruby/rbs typeprof 0.30.1 https://github.com/ruby/typeprof debug 1.11.0 https://github.com/ruby/debug racc 1.8.1 https://github.com/ruby/racc diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb index f0c42866ea5df7..6ca5b1f5f8cd40 100644 --- a/test/openssl/test_pkey_dh.rb +++ b/test/openssl/test_pkey_dh.rb @@ -4,31 +4,42 @@ if defined?(OpenSSL) && defined?(OpenSSL::PKey::DH) class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase - NEW_KEYLEN = 2048 - def test_new_empty - dh = OpenSSL::PKey::DH.new - assert_equal nil, dh.p - assert_equal nil, dh.priv_key + # pkeys are immutable with OpenSSL >= 3.0 + if openssl?(3, 0, 0) + assert_raise(ArgumentError) { OpenSSL::PKey::DH.new } + else + dh = OpenSSL::PKey::DH.new + assert_nil(dh.p) + assert_nil(dh.priv_key) + end end def test_new_generate - # This test is slow - dh = OpenSSL::PKey::DH.new(NEW_KEYLEN) - assert_key(dh) + begin + dh1 = OpenSSL::PKey::DH.new(512) + rescue OpenSSL::PKey::PKeyError + omit "generating 512-bit DH parameters failed; " \ + "likely not supported by this OpenSSL build" + end + assert_equal(512, dh1.p.num_bits) + assert_key(dh1) + + dh2 = OpenSSL::PKey::DH.generate(512) + assert_equal(512, dh2.p.num_bits) + assert_key(dh2) + assert_not_equal(dh1.p, dh2.p) end if ENV["OSSL_TEST_ALL"] == "1" def test_new_break unless openssl? && OpenSSL.fips_mode - assert_nil(OpenSSL::PKey::DH.new(NEW_KEYLEN) { break }) assert_raise(RuntimeError) do - OpenSSL::PKey::DH.new(NEW_KEYLEN) { raise } + OpenSSL::PKey::DH.new(2048) { raise } end else # The block argument is not executed in FIPS case. # See https://github.com/ruby/openssl/issues/692 for details. - assert(OpenSSL::PKey::DH.new(NEW_KEYLEN) { break }) - assert(OpenSSL::PKey::DH.new(NEW_KEYLEN) { raise }) + assert_kind_of(OpenSSL::PKey::DH, OpenSSL::PKey::DH.new(2048) { raise }) end end @@ -51,15 +62,15 @@ def test_derive_key end def test_DHparams - dh = Fixtures.pkey("dh2048_ffdhe2048") - dh_params = dh.public_key + dh_params = Fixtures.pkey("dh2048_ffdhe2048") asn1 = OpenSSL::ASN1::Sequence([ - OpenSSL::ASN1::Integer(dh.p), - OpenSSL::ASN1::Integer(dh.g) + OpenSSL::ASN1::Integer(dh_params.p), + OpenSSL::ASN1::Integer(dh_params.g) ]) + assert_equal(asn1.to_der, dh_params.to_der) key = OpenSSL::PKey::DH.new(asn1.to_der) - assert_same_dh dh_params, key + assert_same_dh_params(dh_params, key) pem = <<~EOF -----BEGIN DH PARAMETERS----- @@ -71,14 +82,20 @@ def test_DHparams ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== -----END DH PARAMETERS----- EOF + assert_equal(pem, dh_params.export) key = OpenSSL::PKey::DH.new(pem) - assert_same_dh dh_params, key + assert_same_dh_params(dh_params, key) + assert_no_key(key) key = OpenSSL::PKey.read(pem) - assert_same_dh dh_params, key - - assert_equal asn1.to_der, dh.to_der - assert_equal pem, dh.export + assert_same_dh_params(dh_params, key) + assert_no_key(key) + + key = OpenSSL::PKey.generate_key(dh_params) + assert_same_dh_params(dh_params, key) + assert_key(key) + assert_equal(dh_params.to_der, key.to_der) + assert_equal(dh_params.to_pem, key.to_pem) end def test_public_key @@ -91,14 +108,14 @@ def test_public_key def test_generate_key # Deprecated in v3.0.0; incompatible with OpenSSL 3.0 - # Creates a copy with params only - dh = Fixtures.pkey("dh2048_ffdhe2048").public_key + dh = Fixtures.pkey("dh2048_ffdhe2048") assert_no_key(dh) dh.generate_key! assert_key(dh) - dh2 = dh.public_key + dh2 = OpenSSL::PKey::DH.new(dh.to_der) dh2.generate_key! + assert_not_equal(dh.pub_key, dh2.pub_key) assert_equal(dh.compute_key(dh2.pub_key), dh2.compute_key(dh.pub_key)) end if !openssl?(3, 0, 0) @@ -204,14 +221,14 @@ def assert_no_key(dh) end def assert_key(dh) - assert(dh.public?) - assert(dh.private?) - assert(dh.pub_key) - assert(dh.priv_key) + assert_true(dh.public?) + assert_true(dh.private?) + assert_kind_of(OpenSSL::BN, dh.pub_key) + assert_kind_of(OpenSSL::BN, dh.priv_key) end - def assert_same_dh(expected, key) - check_component(expected, key, [:p, :q, :g, :pub_key, :priv_key]) + def assert_same_dh_params(expected, key) + check_component(expected, key, [:p, :q, :g]) end end diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb index f3324b04af258b..0779483bd482b1 100644 --- a/test/openssl/test_pkey_dsa.rb +++ b/test/openssl/test_pkey_dsa.rb @@ -34,9 +34,14 @@ def test_new_break end def test_new_empty - key = OpenSSL::PKey::DSA.new - assert_nil(key.p) - assert_raise(OpenSSL::PKey::PKeyError) { key.to_der } + # pkeys are immutable with OpenSSL >= 3.0 + if openssl?(3, 0, 0) + assert_raise(ArgumentError) { OpenSSL::PKey::DSA.new } + else + key = OpenSSL::PKey::DSA.new + assert_nil(key.p) + assert_raise(OpenSSL::PKey::PKeyError) { key.to_der } + end end def test_generate diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb index e569397c0a874c..58857cb038b10b 100644 --- a/test/openssl/test_pkey_ec.rb +++ b/test/openssl/test_pkey_ec.rb @@ -4,19 +4,9 @@ if defined?(OpenSSL) class OpenSSL::TestEC < OpenSSL::PKeyTestCase - def test_ec_key + def test_ec_key_new key1 = OpenSSL::PKey::EC.generate("prime256v1") - # PKey is immutable in OpenSSL >= 3.0; constructing an empty EC object is - # deprecated - if !openssl?(3, 0, 0) - key2 = OpenSSL::PKey::EC.new - key2.group = key1.group - key2.private_key = key1.private_key - key2.public_key = key1.public_key - assert_equal key1.to_der, key2.to_der - end - key3 = OpenSSL::PKey::EC.new(key1) assert_equal key1.to_der, key3.to_der @@ -35,6 +25,23 @@ def test_ec_key end end + def test_ec_key_new_empty + # pkeys are immutable with OpenSSL >= 3.0; constructing an empty EC object is + # disallowed + if openssl?(3, 0, 0) + assert_raise(ArgumentError) { OpenSSL::PKey::EC.new } + else + key = OpenSSL::PKey::EC.new + assert_nil(key.group) + + p256 = Fixtures.pkey("p256") + key.group = p256.group + key.private_key = p256.private_key + key.public_key = p256.public_key + assert_equal(p256.to_der, key.to_der) + end + end + def test_builtin_curves builtin_curves = OpenSSL::PKey::EC.builtin_curves assert_not_empty builtin_curves diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb index 850c16a029e1d3..6a8768d1fffb3b 100644 --- a/test/openssl/test_pkey_rsa.rb +++ b/test/openssl/test_pkey_rsa.rb @@ -61,6 +61,16 @@ def test_new_public_exponent assert_equal 3, key.e end + def test_new_empty + # pkeys are immutable with OpenSSL >= 3.0 + if openssl?(3, 0, 0) + assert_raise(ArgumentError) { OpenSSL::PKey::RSA.new } + else + key = OpenSSL::PKey::RSA.new + assert_nil(key.n) + end + end + def test_s_generate key1 = OpenSSL::PKey::RSA.generate(2048) assert_equal 2048, key1.n.num_bits @@ -181,7 +191,7 @@ def test_verify_empty_rsa assert_raise(OpenSSL::PKey::PKeyError, "[Bug #12783]") { rsa.verify("SHA1", "a", "b") } - end + end unless openssl?(3, 0, 0) # Empty RSA is not possible with OpenSSL >= 3.0 def test_sign_verify_pss key = Fixtures.pkey("rsa2048") diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb index 937cf44e190a56..683d53f339f8c2 100644 --- a/test/ruby/test_zjit.rb +++ b/test/ruby/test_zjit.rb @@ -1642,7 +1642,7 @@ def test(c) = c.foo }, call_threshold: 2, insns: [:opt_send_without_block] end - def test_attr_accessor_getivar + def test_attr_accessor assert_compiles '[4, 4]', %q{ class C attr_accessor :foo @@ -1658,47 +1658,6 @@ def test(c) = c.foo }, call_threshold: 2, insns: [:opt_send_without_block] end - def test_attr_accessor_setivar - assert_compiles '[5, 5]', %q{ - class C - attr_accessor :foo - - def initialize - @foo = 4 - end - end - - def test(c) - c.foo = 5 - c.foo - end - - c = C.new - [test(c), test(c)] - }, call_threshold: 2, insns: [:opt_send_without_block] - end - - def test_attr_writer - assert_compiles '[5, 5]', %q{ - class C - attr_writer :foo - - def initialize - @foo = 4 - end - - def get_foo = @foo - end - - def test(c) - c.foo = 5 - c.get_foo - end - c = C.new - [test(c), test(c)] - }, call_threshold: 2, insns: [:opt_send_without_block] - end - def test_uncached_getconstant_path assert_compiles RUBY_COPYRIGHT.dump, %q{ def test = RUBY_COPYRIGHT diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index 824b35f7673dc3..d81231e2820b88 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -1986,24 +1986,6 @@ impl Function { } let getivar = self.push_insn(block, Insn::GetIvar { self_val: recv, id, state }); self.make_equal_to(insn_id, getivar); - } else if def_type == VM_METHOD_TYPE_ATTRSET && args.len() == 1 { - self.push_insn(block, Insn::PatchPoint { invariant: Invariant::MethodRedefined { klass, method: mid, cme }, state }); - if let Some(profiled_type) = profiled_type { - recv = self.push_insn(block, Insn::GuardType { val: recv, guard_type: Type::from_profiled_type(profiled_type), state }); - } - let id = unsafe { get_cme_def_body_attr_id(cme) }; - - // Check if we're accessing ivars of a Class or Module object as they require single-ractor mode. - // We omit gen_prepare_non_leaf_call on gen_setivar, so it's unsafe to raise for multi-ractor mode. - if unsafe { rb_zjit_singleton_class_p(klass) } { - let attached = unsafe { rb_class_attached_object(klass) }; - if unsafe { RB_TYPE_P(attached, RUBY_T_CLASS) || RB_TYPE_P(attached, RUBY_T_MODULE) } { - self.push_insn(block, Insn::PatchPoint { invariant: Invariant::SingleRactorMode, state }); - } - } - let val = args[0]; - let setivar = self.push_insn(block, Insn::SetIvar { self_val: recv, id, val, state }); - self.make_equal_to(insn_id, setivar); } else { if let Insn::SendWithoutBlock { def_type: insn_def_type, .. } = &mut self.insns[insn_id.0] { *insn_def_type = Some(MethodType::from(def_type)); @@ -12151,66 +12133,4 @@ mod opt_tests { Return v25 "); } - - #[test] - fn test_inline_attr_accessor_set() { - eval(" - class C - attr_accessor :foo - end - - def test(o) = o.foo = 5 - test C.new - test C.new - "); - assert_snapshot!(hir_string("test"), @r" - fn test@:6: - bb0(): - EntryPoint interpreter - v1:BasicObject = LoadSelf - v2:BasicObject = GetLocal l0, SP@4 - Jump bb2(v1, v2) - bb1(v5:BasicObject, v6:BasicObject): - EntryPoint JIT(0) - Jump bb2(v5, v6) - bb2(v8:BasicObject, v9:BasicObject): - v14:Fixnum[5] = Const Value(5) - PatchPoint MethodRedefined(C@0x1000, foo=@0x1008, cme:0x1010) - v23:HeapObject[class_exact:C] = GuardType v9, HeapObject[class_exact:C] - SetIvar v23, :@foo, v14 - CheckInterrupts - Return v14 - "); - } - - #[test] - fn test_inline_attr_writer_set() { - eval(" - class C - attr_writer :foo - end - - def test(o) = o.foo = 5 - test C.new - test C.new - "); - assert_snapshot!(hir_string("test"), @r" - fn test@:6: - bb0(): - EntryPoint interpreter - v1:BasicObject = LoadSelf - v2:BasicObject = GetLocal l0, SP@4 - Jump bb2(v1, v2) - bb1(v5:BasicObject, v6:BasicObject): - EntryPoint JIT(0) - Jump bb2(v5, v6) - bb2(v8:BasicObject, v9:BasicObject): - v14:Fixnum[5] = Const Value(5) - PatchPoint MethodRedefined(C@0x1000, foo=@0x1008, cme:0x1010) - v23:HeapObject[class_exact:C] = GuardType v9, HeapObject[class_exact:C] - SetIvar v23, :@foo, v14 - CheckInterrupts - Return v14 - "); - } }