{"id":"de430bee90fb28ec","repo":"rust-lang/rust","slug":"unexpected-additive-operation","errorCode":null,"errorMessage":"unexpected additive operation {:?}","messagePattern":"unexpected additive operation (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_codegen_gcc/src/int.rs","lineNumber":187,"sourceCode":"                if a_type.is_vector() {\n                    // Vector types need to be bitcast.\n                    // FIXME(antoyo): perhaps use __builtin_convertvector for vector casting.\n                    b = self.context.new_bitcast(self.location, b, a_type);\n                } else {\n                    b = self.context.new_cast(self.location, b, a_type);\n                }\n            }\n            self.context.new_binary_op(self.location, operation, a_type, a, b)\n        } else {\n            debug_assert!(a_type.dyncast_array().is_some());\n            debug_assert!(b_type.dyncast_array().is_some());\n            let signed = a_type.is_compatible_with(self.i128_type);\n            let func_name = match (operation, signed) {\n                (BinaryOp::Plus, true) => \"__rust_i128_add\",\n                (BinaryOp::Plus, false) => \"__rust_u128_add\",\n                (BinaryOp::Minus, true) => \"__rust_i128_sub\",\n                (BinaryOp::Minus, false) => \"__rust_u128_sub\",\n                _ => unreachable!(\"unexpected additive operation {:?}\", operation),\n            };\n            let param_a = self.context.new_parameter(self.location, a_type, \"a\");\n            let param_b = self.context.new_parameter(self.location, b_type, \"b\");\n            let func = self.context.new_function(\n                self.location,\n                FunctionType::Extern,\n                a_type,\n                &[param_a, param_b],\n                func_name,\n                false,\n            );\n            self.context.new_call(self.location, func, &[a, b])\n        }\n    }\n\n    pub fn gcc_add(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {\n        self.additive_operation(BinaryOp::Plus, a, b)\n    }","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_codegen_gcc/src/int.rs#L169-L205","documentation":"In `Builder::additive_operation` the match over `(operation, signed)` only arms `BinaryOp::Plus` and `BinaryOp::Minus` (dispatched to `__rust_i128_add`/`__rust_u128_add`/`__rust_i128_sub`/`__rust_u128_sub`). Any other `BinaryOp` reaching this branch (e.g. `Mult`, `Divide`, `Modulo`, or a bitwise op) trips `unreachable!`.","triggerScenarios":"`additive_operation` is called (via `gcc_add`/`gcc_sub`) but with a `BinaryOp` other than `Plus`/`Minus`, while the operands are non-native 128-bit integers. The public API (`gcc_add`, `gcc_sub`) only ever passes `Plus`/`Minus`, so this fires only when an internal caller is wired to the wrong helper — e.g. someone routing `gcc_mul` through `additive_operation` by mistake.","commonSituations":"A regression in a refactor that moves multiplicative ops into `additive_operation`, or a custom fork that added a new BinaryOp variant without extending the match. Not user-facing in stock rustc — purely an internal-invariant violation.","solutions":["Find the caller passing the unexpected `BinaryOp` (search for `.additive_operation(` and check the op).","Route multiplication/division/modulo through `multiplicative_operation` instead, which selects `__muloti4`/`__udivti3`/etc.","If you genuinely need a new additive op, add an arm mapping it to the correct `__rust_i128_*`/`__rust_u128_*` runtime symbol."],"exampleFix":"// before\nlet func_name = match (operation, signed) {\n    (BinaryOp::Plus, true) => \"__rust_i128_add\",\n    (BinaryOp::Plus, false) => \"__rust_u128_add\",\n    (BinaryOp::Minus, true) => \"__rust_i128_sub\",\n    (BinaryOp::Minus, false) => \"__rust_u128_sub\",\n    _ => unreachable!(\"unexpected additive operation {:?}\", operation),\n};\n\n// after (defensive: route multiplicative ops to the right helper, fail loudly otherwise)\nlet func_name = match (operation, signed) {\n    (BinaryOp::Plus, true) => \"__rust_i128_add\",\n    (BinaryOp::Plus, false) => \"__rust_u128_add\",\n    (BinaryOp::Minus, true) => \"__rust_i128_sub\",\n    (BinaryOp::Minus, false) => \"__rust_u128_sub\",\n    other => panic!(\"additive_operation called with non-additive op {:?}; use multiplicative_operation\", other),\n};","handlingStrategy":"validation","validationCode":"// additive_operation only supports BinaryOp::Plus and BinaryOp::Minus.\n// Validate before dispatching a BinaryOp into it.\nuse gccjit::BinaryOp;\nfn is_additive(op: BinaryOp) -> bool {\n    matches!(op, BinaryOp::Plus | BinaryOp::Minus)\n}\nif !is_additive(operation) {\n    return Err(format!(\"additive_operation: unsupported op {:?}; use gcc_mul/gcc_sdiv instead\", operation));\n}\nbuilder.additive_operation(operation, a, b)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["additive_operation is a private dispatcher; always enter it through the public gcc_add (Plus) and gcc_sub (Minus) wrappers, never with Mult/Divide/Modulo.","If you extend the backend with a new BinaryOp, update the match arms in additive_operation at the same time rather than relying on the unreachable fallback.","Treat the unreachable! as a hard contract: Plus/Minus only. Add a debug_assert!(is_additive(operation)) at the call site during development."],"tags":["rustc-codegen-gcc","ice","binaryop","additive","i128"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}