rust-lang/rust · error
struct type
Error message
struct type
What it means
`const_struct` in `common.rs:298-304` builds an anonymous struct type via `self.type_struct(&fields, packed)` then asserts `typ.is_struct().expect("struct type")`. The panic means the type returned by `type_struct` is not recognized as a struct by `is_struct()`. rustc_codegen_gcc relies on the gccjit `Type::is_struct` returning `Some` for freshly-created struct types; if it returns `None`, the codegen cannot construct the struct value. This is a type-system invariant violation in the backend, typically caused by a mismatch between how `type_struct` produces a type and how `is_struct` inspects it (e.g. an opaque/record type, a vectorized type, or a binding version difference).
Source
Thrown at compiler/rustc_codegen_gcc/src/common.rs:302
let mut const_str_cache = self.const_str_cache.borrow_mut();
let str_global = const_str_cache.get(s).copied().unwrap_or_else(|| {
let g = self.global_string(s);
const_str_cache.insert(s.to_owned(), g);
g
});
let len = s.len();
let cs = self.const_ptrcast(
str_global.get_address(None),
self.type_ptr_to(self.layout_of(self.tcx.types.str_).gcc_type(self)),
);
(cs, self.const_usize(len as u64))
}
fn const_struct(&self, values: &[RValue<'gcc>], packed: bool) -> RValue<'gcc> {
let fields: Vec<_> = values.iter().map(|value| value.get_type()).collect();
// FIXME(antoyo): cache the type? It's anonymous, so probably not.
let typ = self.type_struct(&fields, packed);
let struct_type = typ.is_struct().expect("struct type");
self.context.new_struct_constructor(None, struct_type.as_type(), None, values)
}
fn const_vector(&self, values: &[RValue<'gcc>]) -> RValue<'gcc> {
let typ = self.type_vector(values[0].get_type(), values.len() as u64);
self.context.new_rvalue_from_vector(None, typ, values)
}
fn const_to_opt_uint(&self, _v: RValue<'gcc>) -> Option<u64> {
// FIXME(antoyo)
None
}
fn const_to_opt_u128(&self, _v: RValue<'gcc>, _sign_ext: bool) -> Option<u128> {
// FIXME(antoyo)
None
}
View on GitHub (pinned to 22057b88b0)
Solutions
- Inspect the value of `typ` (dump via debug) right before the `is_struct()` call to confirm whether gccjit returns a struct or a different kind (union/opaque/vector).
- Reproduce with the matching libgccjit version pinned in the project; the most common cause is a libgccjit/gccjit-crate version skew — align them.
- If `type_struct` legitimately returns a non-struct for some inputs, guard `const_struct`: short-circuit single-field or empty cases instead of forcing `is_struct`.
- Report upstream to rustc_codegen_gcc with the field type list and libgccjit version, since `is_struct` returning `None` for a just-created struct is a backend contract break.
Example fix
// before
let struct_type = typ.is_struct().expect("struct type");
self.context.new_struct_constructor(None, struct_type.as_type(), None, values)
// after (diagnose instead of asserting blindly)
let struct_type = typ.is_struct().unwrap_or_else(|| {
panic!("const_struct: type_struct did not yield a struct (kind={:?}, fields={}, packed={})",
typ, values.len(), packed);
});
self.context.new_struct_constructor(None, struct_type.as_type(), None, values) Defensive patterns
Strategy: type-guard
Type guard
// common.rs:302 -> typ.is_struct().expect("struct type") inside const_struct.
// Narrow before constructing so a mismatch yields a Result, not a panic.
fn safe_const_struct<'gcc>(
cx: &CodegenCx<'gcc, '_>,
values: &[RValue<'gcc>],
packed: bool,
) -> Option<RValue<'gcc>> {
let fields: Vec<_> = values.iter().map(|v| v.get_type()).collect();
let typ = cx.type_struct(&fields, packed);
let struct_type = typ.is_struct()?;
Some(cx.context.new_struct_constructor(None, struct_type.as_type(), None, values))
} Prevention
- Every field RValue must originate from the same GCC context as the struct; cross-context fields can make type_struct return a non-struct type.
- Watch empty field lists: type_struct may not produce a struct kind for zero fields, so special-case them before calling const_struct.
- Ensure the packed flag matches the source aggregate; packed vs unpacked lowering can change the resulting GCC type kind.
When it happens
Trigger: Calling `const_struct(values, packed)` where `type_struct` yields a type for which `Type::is_struct()` returns `None`. Likely with zero fields, a single field that gccjit represents as a non-record, very large field counts, or when the gccjit bindings version changed the representation of anonymous structs.
Common situations: Encountered after upgrading the `gccjit` crate / libgccjit version where struct-type representation changed; building a crate with anonymous struct constants whose field shape trips an edge case in `type_struct`; deviating local patches to `type_of.rs`/`type.rs` that break the struct-type contract.
Related errors
- func
- Can't get the layout of `i128`
- cannot allocate registers
- first index in inbounds_gep
- Called extract_element on a non-vector type
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/e35da109ec8d5b6b.json.
Report an issue: GitHub.