rust-lang/rust · error

first index in inbounds_gep

Error message

first index in inbounds_gep

What it means

Thrown by the `inbounds_gep` implementation of rustc's `BuilderMethods` trait in rustc_codegen_gcc. After casting the pointer for opaque-pointer support, it does `indices.next().expect("first index in inbounds_gep")`, so it panics if the `indices` slice passed by rustc's codegen is empty. A get-element-pointer (GEP) operation always needs at least one index to compute an offset from a base pointer, so an empty slice is a contract violation between rustc and the GCC backend.

Source

Thrown at compiler/rustc_codegen_gcc/src/builder.rs:1242

            #[cfg(not(feature = "master"))]
            let pointee_size =
                self.context.new_rvalue_from_int(index.get_type(), pointee_type.get_size() as i32);
            result = result + self.gcc_int_cast(*index * pointee_size, self.sizet_type);
        }
        self.context.new_bitcast(self.location, result, ptr_type)
    }

    fn inbounds_gep(
        &mut self,
        typ: Type<'gcc>,
        ptr: RValue<'gcc>,
        indices: &[RValue<'gcc>],
    ) -> RValue<'gcc> {
        // NOTE: due to opaque pointers now being used, we need to cast here.
        let ptr = self.context.new_cast(self.location, ptr, typ.make_pointer());
        // NOTE: array indexing is always considered in bounds in GCC (FIXME(antoyo): to be verified).
        let mut indices = indices.iter();
        let index = indices.next().expect("first index in inbounds_gep");
        let mut result = self.context.new_array_access(self.location, ptr, *index);
        for index in indices {
            result = self.context.new_array_access(self.location, result, *index);
        }
        result.get_address(self.location)
    }

    /* Casts */
    fn trunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        // FIXME(antoyo): check that it indeed truncate the value.
        self.gcc_int_cast(value, dest_ty)
    }

    fn sext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        // FIXME(antoyo): check that it indeed sign extend the value.
        if dest_ty.dyncast_vector().is_some() {
            // FIXME(antoyo): nothing to do as it is only for LLVM?
            return value;

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Confirm the panic reproduces only under `-Zcodegen-backend=gcc` and not the default LLVM backend; if LLVM-only, it is a rustc_codegen_gcc bug
  2. Rebuild rustc_codegen_gcc against the exact rustc commit/toolchain version it ships with (mismatched versions are the dominant cause)
  3. Isolate the offending construct in a minimal crate and file an issue on rustc_codegen_gcc with the MIR/IR
  4. As a local workaround, patch `inbounds_gep` to return the cast pointer unchanged when `indices` is empty

Example fix

// before
let mut indices = indices.iter();
let index = indices.next().expect("first index in inbounds_gep");
let mut result = self.context.new_array_access(self.location, ptr, *index);
for index in indices {
    result = self.context.new_array_access(self.location, result, *index);
}
result.get_address(self.location)

// after
let mut indices = indices.iter();
let mut result = match indices.next() {
    Some(index) => self.context.new_array_access(self.location, ptr, *index),
    None => return ptr,
};
for index in indices {
    result = self.context.new_array_access(self.location, result, *index);
}
result.get_address(self.location)
Defensive patterns

Strategy: validation

Validate before calling

// inbounds_gep panics via .expect() when `indices` is empty.
// Validate the slice length BEFORE calling the backend.
if indices.is_empty() {
    return Err("inbounds_gep requires at least one index (the structural pointer index)");
}
let first = indices[0];
// ...now safe to call builder.inbounds_gep(typ, ptr, indices)

Prevention

When it happens

Trigger: rustc's MIR-to-backend lowering emits an `inbounds_gep` instruction with an empty `indices` array (e.g. a zero-offset pointer projection or a codegen path that folded all indices away but still emitted the GEP call). The panic fires on the very first line of `inbounds_gep` before any array access is built.

Common situations: Almost always a symptom of cg_gcc lagging behind the exact rustc toolchain it was built against (the backend tracks specific rustc commits). Also seen with zero-sized type access, `repr(packed)` struct field projection, or after upstream rustc changes to how GEP indices are generated on nightly.

Related errors


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