rust-lang/rust · error

internal error: entered unreachable code

Error message

internal error: entered unreachable code

What it means

Inside `gcc_checked_binop`, on the non-native-int path for `OverflowOp::Add`, the match on `new_kind` only arms `Int(I128)` and `Uint(U128)` (mapping to `__rust_i128_addo`/`__rust_u128_addo`). Any other width reaching this branch is unreachable: on a platform where the int is non-native, only i128/u128 qualify; i8–i64 are expected to be native and use `__builtin_add_overflow`.

Source

Thrown at compiler/rustc_codegen_gcc/src/int.rs:299

            Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)),
            Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.pointer_width)),
            t @ (Uint(_) | Int(_)) => t,
            _ => panic!("tried to get overflow intrinsic for op applied to non-int type"),
        };

        // FIXME(antoyo): remove duplication with intrinsic?
        let name = if self.is_native_int_type(lhs.get_type()) {
            match oop {
                OverflowOp::Add => "__builtin_add_overflow",
                OverflowOp::Sub => "__builtin_sub_overflow",
                OverflowOp::Mul => "__builtin_mul_overflow",
            }
        } else {
            let (func_name, width) = match oop {
                OverflowOp::Add => match new_kind {
                    Int(I128) => ("__rust_i128_addo", 128),
                    Uint(U128) => ("__rust_u128_addo", 128),
                    _ => unreachable!(),
                },
                OverflowOp::Sub => match new_kind {
                    Int(I128) => ("__rust_i128_subo", 128),
                    Uint(U128) => ("__rust_u128_subo", 128),
                    _ => unreachable!(),
                },
                OverflowOp::Mul => match new_kind {
                    Int(I32) => ("__mulosi4", 32),
                    Int(I64) => ("__mulodi4", 64),
                    Int(I128) => ("__rust_i128_mulo", 128), // FIXME(antoyo): use __muloti4d instead?
                    Uint(U128) => ("__rust_u128_mulo", 128),
                    _ => unreachable!(),
                },
            };
            return self.operation_with_overflow(func_name, lhs, rhs, width);
        };

        let intrinsic = self.context.get_builtin_function(name);

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Verify `is_native_int_type` against the target pointer width: i8/i16/i32/i64 must be native on 64-bit, i8/i16/i32 on 32-bit.
  2. Dump `lhs.get_type()` and `new_kind` at the call to confirm which one is wrong.
  3. If a genuinely non-native width is needed (e.g. non-native i64), add an arm with the correct compiler-rt symbol (`__mulosi4`-style for add).
  4. Add a target-specific test for the platform that triggered it.

Example fix

// before
OverflowOp::Add => match new_kind {
    Int(I128) => ("__rust_i128_addo", 128),
    Uint(U128) => ("__rust_u128_addo", 128),
    _ => unreachable!(),
},

// after
OverflowOp::Add => match new_kind {
    Int(I128) => ("__rust_i128_addo", 128),
    Uint(U128) => ("__rust_u128_addo", 128),
    other => unreachable!("non-native add overflow for unexpected kind {:?}", other),
},
Defensive patterns

Strategy: fallback

Validate before calling

// Non-native overflow Add is only implemented for i128/u128 (width 128).
// If lhs is non-native but the resolved kind is not 128-bit, route elsewhere.
use rustc_middle::ty::{IntTy::*, UintTy::*, Int, Uint};
let native = builder.is_native_int_type(lhs.get_type());
let width_ok = match *typ.kind() {
    Int(I128) | Uint(U128) => true,
    _ => native, // native ints use __builtin_add_overflow and are fine
};
if !width_ok {
    return Err("overflow Add: gcc backend only emulates i128/u128; rebuild with LLVM backend");
}

Try / catch

// gcc backend panics on non-native overflow Add for non-128 widths.
// Catch the unwind and retry compilation with the LLVM backend.
use std::panic::{catch_unwind, AssertUnwindSafe};
let res = catch_unwind(AssertUnwindSafe(|| {
    builder.gcc_checked_binop(OverflowOp::Add, typ, lhs, rhs)
}));
match res {
    Ok(v) => v,
    Err(_) => {
        eprintln!("gcc backend cannot emulate overflow Add for {:?}; falling back to LLVM");
        rebuild_with_backend("llvm")?;
    }
}

Prevention

When it happens

Trigger: `is_native_int_type(lhs.get_type())` returns false for a type whose `new_kind` is not `I128`/`U128` (e.g. an i64 wrongly classified as non-native). The contradiction between type classification and width trips the unreachable.

Common situations: Misclassification of an integer's native-ness for the current target pointer width (32-bit target treating i64 as non-native, or a custom ABI). Also appears after changes to `is_native_int_type` that desync from the `new_kind` derivation.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/31e5204359c0cc60.json. Report an issue: GitHub.