Skip to content

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

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions