rust-lang/rust · error

non-array a value

Error message

non-array a value

What it means

In `CodegenCx::operation_with_overflow` (the helper invoked for non-`__builtin_*` overflow ops), the code asserts that `lhs`'s type is an array (the i128/u128-as-two-i64 representation) and recovers its element type via `dyncast_array().expect("non-array a value")`. If `lhs.get_type()` is not an array — e.g. a native int slipped through, or a pointer/aggregate — the expect fails.

Source

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

    ) -> (RValue<'gcc>, RValue<'gcc>) {
        let a_type = lhs.get_type();
        let b_type = rhs.get_type();
        debug_assert!(a_type.dyncast_array().is_some());
        debug_assert!(b_type.dyncast_array().is_some());
        let overflow_type = self.i32_type;
        let overflow_param_type = overflow_type.make_pointer();
        let res_type = a_type;

        let overflow_value =
            self.current_func().new_local(self.location, overflow_type, "overflow");
        let overflow_addr = overflow_value.get_address(self.location);

        let param_a = self.context.new_parameter(self.location, a_type, "a");
        let param_b = self.context.new_parameter(self.location, b_type, "b");
        let param_overflow =
            self.context.new_parameter(self.location, overflow_param_type, "overflow");

        let a_elem_type = a_type.dyncast_array().expect("non-array a value");
        debug_assert!(a_elem_type.is_integral());
        let res_ty = match width {
            32 => self.tcx.types.i32,
            64 => self.tcx.types.i64,
            128 => self.tcx.types.i128,
            _ => unreachable!("unexpected integer size"),
        };
        let layout = self
            .tcx
            .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(res_ty))
            .unwrap();

        let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) };
        let mut fn_abi = FnAbi {
            args: vec![arg_abi.clone(), arg_abi.clone(), arg_abi.clone()].into_boxed_slice(),
            ret: arg_abi,
            c_variadic: false,
            fixed_count: 3,

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Confirm `is_native_int_type(lhs.get_type())` returned false (otherwise `__builtin_*_overflow` should have been used instead).
  2. Dump `lhs.get_type()` to confirm whether it is really an array; if not, the classification helpers are wrong.
  3. Verify the i128/u128 array layout on this libgccjit version — `concat_low_high` and `dyncast_array` must agree.
  4. If a new non-array non-native type is legitimate, redesign `operation_with_overflow` rather than weakening the expect.

Example fix

// before
let a_elem_type = a_type.dyncast_array().expect("non-array a value");

// after
let a_elem_type = a_type.dyncast_array().unwrap_or_else(|| {
    panic!("operation_with_overflow: lhs is not an i128/u128 array: {:?}", a_type);
});
Defensive patterns

Strategy: type-guard

Validate before calling

// operation_with_overflow requires lhs.get_type().dyncast_array().is_some().
let a_type = lhs.get_type();
if a_type.dyncast_array().is_none() {
    return Err("operation_with_overflow: lhs type is not a gccjit array (expected i128/u128 emulation)");
}
builder.operation_with_overflow(func_name, lhs, rhs, width)

Type guard

/// True when the value's gccjit type is the 2-element array used to
/// emulate a non-native integer (i128/u128 on 32-bit targets).
fn is_emulated_int_array<'gcc>(value: gccjit::RValue<'gcc>) -> bool {
    value.get_type().dyncast_array().is_some()
}

if is_emulated_int_array(lhs) {
    builder.operation_with_overflow(func_name, lhs, rhs, width)
}

Prevention

When it happens

Trigger: `operation_with_overflow` is called with an `lhs` whose GCC type is not the 2-element array used for non-native 128-bit ints. Reached from `gcc_checked_binop` after it has already chosen the non-`__builtin_*` path, so the type classification upstream (`is_native_int_type`) and the assertion here disagree.

Common situations: Same root family as 134–136: type-classification mismatch, custom ABI/target, or a refactor that changed the array representation of i128/u128. Often co-occurs with one of those.

Related errors


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