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
- 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
- Rebuild rustc_codegen_gcc against the exact rustc commit/toolchain version it ships with (mismatched versions are the dominant cause)
- Isolate the offending construct in a minimal crate and file an issue on rustc_codegen_gcc with the MIR/IR
- 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
- Always supply the structural pointer index as the first element of `indices` for any GEP-style helper.
- Treat an empty `indices` slice as a programmer error and reject it at the call site before it reaches the backend.
- In frontends/codegen layers, wrap all GEP emission in a helper that asserts `!indices.is_empty()` so the invariant lives in one place.
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
- not implemented
- Called extract_element on a non-vector type
- pointee type
- internal error: entered unreachable code
- `rustc_codegen_gcc` doesn't support scalable vectors yet
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/416d296197067e51.json.
Report an issue: GitHub.