summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Bernstein <rubybugs@bernsteinbear.com>2025-10-30 13:30:08 -0400
committerGitHub <noreply@github.com>2025-10-30 17:30:08 +0000
commit57f76f62d5e12766465f11ebb0d0b0b0d4d549ce (patch)
treed0df05c96daa9a2cc79d18ad4a88c5bd232e5626
parent481f994449f35ce4050757561e89a776903ee425 (diff)
ZJIT: Fix incorrect self.class.respond_to? folding (#15001)
Right now we have a subtle type system bug around `types::Class`. Until that is resolved, stop marking `Kernel#class` as returning `types::Class`, which fixes Rubocop. Re: https://github.com/Shopify/ruby/issues/850
-rw-r--r--zjit/src/cruby_methods.rs4
-rw-r--r--zjit/src/hir/opt_tests.rs86
-rw-r--r--zjit/src/hir/tests.rs4
3 files changed, 90 insertions, 4 deletions
diff --git a/zjit/src/cruby_methods.rs b/zjit/src/cruby_methods.rs
index 12d226ce51..bd3409ff07 100644
--- a/zjit/src/cruby_methods.rs
+++ b/zjit/src/cruby_methods.rs
@@ -231,7 +231,9 @@ pub fn init() -> Annotations {
annotate_builtin!(rb_mKernel, "Float", types::Float);
annotate_builtin!(rb_mKernel, "Integer", types::Integer);
- annotate_builtin!(rb_mKernel, "class", types::Class, leaf);
+ // TODO(max): Annotate rb_mKernel#class as returning types::Class. Right now there is a subtle
+ // type system bug that causes an issue if we make it return types::Class.
+ annotate_builtin!(rb_mKernel, "class", types::HeapObject, leaf);
annotate_builtin!(rb_mKernel, "frozen?", types::BoolExact);
annotate_builtin!(rb_cSymbol, "name", types::StringExact);
annotate_builtin!(rb_cSymbol, "to_s", types::StringExact);
diff --git a/zjit/src/hir/opt_tests.rs b/zjit/src/hir/opt_tests.rs
index c7764bd290..d697065da9 100644
--- a/zjit/src/hir/opt_tests.rs
+++ b/zjit/src/hir/opt_tests.rs
@@ -2358,7 +2358,7 @@ mod hir_opt_tests {
PatchPoint MethodRedefined(Module@0x1010, class@0x1018, cme:0x1020)
PatchPoint NoSingletonClass(Module@0x1010)
IncrCounter inline_iseq_optimized_send_count
- v26:Class = InvokeBuiltin leaf _bi20, v21
+ v26:HeapObject = InvokeBuiltin leaf _bi20, v21
CheckInterrupts
Return v26
");
@@ -7050,4 +7050,88 @@ mod hir_opt_tests {
Return v19
");
}
+
+ #[test]
+ fn test_fold_self_class_respond_to_true() {
+ eval(r#"
+ class C
+ class << self
+ attr_accessor :_lex_actions
+ private :_lex_actions, :_lex_actions=
+ end
+ self._lex_actions = [1, 2, 3]
+ def initialize
+ if self.class.respond_to?(:_lex_actions, true)
+ :CORRECT
+ else
+ :oh_no_wrong
+ end
+ end
+ end
+ C.new # warm up
+ TEST = C.instance_method(:initialize)
+ "#);
+ assert_snapshot!(hir_string_proc("TEST"), @r"
+ fn initialize@<compiled>:9:
+ bb0():
+ EntryPoint interpreter
+ v1:BasicObject = LoadSelf
+ Jump bb2(v1)
+ bb1(v4:BasicObject):
+ EntryPoint JIT(0)
+ Jump bb2(v4)
+ bb2(v6:BasicObject):
+ PatchPoint MethodRedefined(C@0x1000, class@0x1008, cme:0x1010)
+ PatchPoint NoSingletonClass(C@0x1000)
+ v40:HeapObject[class_exact:C] = GuardType v6, HeapObject[class_exact:C]
+ IncrCounter inline_iseq_optimized_send_count
+ v43:HeapObject = InvokeBuiltin leaf _bi20, v40
+ v12:StaticSymbol[:_lex_actions] = Const Value(VALUE(0x1038))
+ v13:TrueClass = Const Value(true)
+ PatchPoint MethodRedefined(Class@0x1040, respond_to?@0x1048, cme:0x1050)
+ PatchPoint NoSingletonClass(Class@0x1040)
+ v47:ModuleSubclass[class_exact*:Class@VALUE(0x1040)] = GuardType v43, ModuleSubclass[class_exact*:Class@VALUE(0x1040)]
+ PatchPoint MethodRedefined(Class@0x1040, _lex_actions@0x1078, cme:0x1080)
+ PatchPoint NoSingletonClass(Class@0x1040)
+ v51:TrueClass = Const Value(true)
+ IncrCounter inline_cfunc_optimized_send_count
+ CheckInterrupts
+ v22:StaticSymbol[:CORRECT] = Const Value(VALUE(0x10a8))
+ CheckInterrupts
+ Return v22
+ ");
+ }
+
+ #[test]
+ fn test_fold_self_class_name() {
+ eval(r#"
+ class C; end
+ def test(o) = o.class.name
+ test(C.new)
+ "#);
+ assert_snapshot!(hir_string("test"), @r"
+ fn test@<compiled>:3:
+ 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):
+ PatchPoint MethodRedefined(C@0x1000, class@0x1008, cme:0x1010)
+ PatchPoint NoSingletonClass(C@0x1000)
+ v24:HeapObject[class_exact:C] = GuardType v9, HeapObject[class_exact:C]
+ IncrCounter inline_iseq_optimized_send_count
+ v27:HeapObject = InvokeBuiltin leaf _bi20, v24
+ PatchPoint MethodRedefined(Class@0x1038, name@0x1040, cme:0x1048)
+ PatchPoint NoSingletonClass(Class@0x1038)
+ v31:ModuleSubclass[class_exact*:Class@VALUE(0x1038)] = GuardType v27, ModuleSubclass[class_exact*:Class@VALUE(0x1038)]
+ IncrCounter inline_cfunc_optimized_send_count
+ v33:StringExact|NilClass = CCall name@0x1070, v31
+ CheckInterrupts
+ Return v33
+ ");
+ }
}
diff --git a/zjit/src/hir/tests.rs b/zjit/src/hir/tests.rs
index df14ba5a7c..32c71dc5d3 100644
--- a/zjit/src/hir/tests.rs
+++ b/zjit/src/hir/tests.rs
@@ -2712,9 +2712,9 @@ pub mod hir_build_tests {
EntryPoint JIT(0)
Jump bb2(v4)
bb2(v6:BasicObject):
- v11:Class = InvokeBuiltin leaf _bi20, v6
+ v11:HeapObject = InvokeBuiltin leaf _bi20, v6
Jump bb3(v6, v11)
- bb3(v13:BasicObject, v14:Class):
+ bb3(v13:BasicObject, v14:HeapObject):
CheckInterrupts
Return v14
");