Skip to content

BigDecimal#+, #-, #add, #sub always try to cast result of coercion to RubyBigDecimal #9194

@trinistr

Description

@trinistr

Environment Information

JRuby version:

  • jruby 10.0.3.0-SNAPSHOT (3.4.5) 2025-11-30 ffffffffff OpenJDK 64-Bit Server VM 21.0.9+10 on 21.0.9+10 +indy +jit [x86_64-linux] (latest commit on master)

OS:

  • Linux 6.18.4-1-MANJARO #1 SMP PREEMPT_DYNAMIC Thu, 08 Jan 2026 12:46:08 +0000 x86_64 GNU/Linux (probably irrelevant)

Expected Behavior

  • Run irb -r bigdecimal
  • Input BigDecimal(10) + Complex(1, 2)
  • Expected result: => (0.11e2+2i)

(ruby 3.4.8 (2025-12-17 revision 995b59f666) +PRISM [x86_64-linux])

Actual Behavior

Error on cast:

irb(main):001> BigDecimal(10) + Complex(1, 2)
org.jruby.dist/org.jruby.ext.bigdecimal.RubyBigDecimal.addInternal(RubyBigDecimal.java:1270): class org.jruby.RubyComplex cannot be cast to class org.jruby.ext.bigdecimal.RubyBigDecimal (org.jruby.RubyComplex and org.jruby.ext.bigdecimal.RubyBigDecimal are in module org.jruby.dist of loader 'app') (Java::JavaLang::ClassCastException)
        from org.jruby.dist/org.jruby.ext.bigdecimal.RubyBigDecimal.op_plus(RubyBigDecimal.java:1253)
        from org.jruby.dist/org.jruby.ext.bigdecimal.RubyBigDecimal$INVOKER$i$1$0$op_plus.call(RubyBigDecimal$INVOKER$i$1$0$op_plus.gen)
        from org.jruby.dist/org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:466)
        from org.jruby.dist/org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:244)
        from org.jruby.dist/org.jruby.runtime.callsite.PlusCallSite.call(PlusCallSite.java:44)
        from org.jruby.dist/org.jruby.ir.interpreter.InterpreterEngine.processCall(InterpreterEngine.java:320)
        from org.jruby.dist/org.jruby.ir.interpreter.StartupInterpreterEngine.interpret(StartupInterpreterEngine.java:66)
        from org.jruby.dist/org.jruby.ir.interpreter.Interpreter.INTERPRET_EVAL(Interpreter.java:110)
        from org.jruby.dist/org.jruby.ir.interpreter.Interpreter.evalCommon(Interpreter.java:242)
        from org.jruby.dist/org.jruby.ir.interpreter.Interpreter.evalWithBinding(Interpreter.java:267)
        from org.jruby.dist/org.jruby.RubyKernel.evalCommon(RubyKernel.java:1301)
        from org.jruby.dist/org.jruby.RubyKernel.eval(RubyKernel.java:1268)
        from org.jruby.dist/org.jruby.RubyKernel$INVOKER$s$0$3$eval.call(RubyKernel$INVOKER$s$0$3$eval.gen)
        from org.jruby.dist/org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:446)
        from org.jruby.dist/org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:92)
        from org.jruby.dist/org.jruby.ir.instructions.CallBase.interpret(CallBase.java:556)
        ... 133 levels...

The problem is in this code in addInternal():

RubyBigDecimal ret = (RubyBigDecimal) callCoerced(context, sites(context).op_plus, b, true);

Result of coercion may not be a BigDecimal, but this assumes it is. subInternal() does a similar thing.

As far as I could tell, no other method does a cast like this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions