{"id":"e35da109ec8d5b6b","repo":"rust-lang/rust","slug":"struct-type","errorCode":null,"errorMessage":"struct type","messagePattern":"struct type","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_codegen_gcc/src/common.rs","lineNumber":302,"sourceCode":"        let mut const_str_cache = self.const_str_cache.borrow_mut();\n        let str_global = const_str_cache.get(s).copied().unwrap_or_else(|| {\n            let g = self.global_string(s);\n            const_str_cache.insert(s.to_owned(), g);\n            g\n        });\n        let len = s.len();\n        let cs = self.const_ptrcast(\n            str_global.get_address(None),\n            self.type_ptr_to(self.layout_of(self.tcx.types.str_).gcc_type(self)),\n        );\n        (cs, self.const_usize(len as u64))\n    }\n\n    fn const_struct(&self, values: &[RValue<'gcc>], packed: bool) -> RValue<'gcc> {\n        let fields: Vec<_> = values.iter().map(|value| value.get_type()).collect();\n        // FIXME(antoyo): cache the type? It's anonymous, so probably not.\n        let typ = self.type_struct(&fields, packed);\n        let struct_type = typ.is_struct().expect(\"struct type\");\n        self.context.new_struct_constructor(None, struct_type.as_type(), None, values)\n    }\n\n    fn const_vector(&self, values: &[RValue<'gcc>]) -> RValue<'gcc> {\n        let typ = self.type_vector(values[0].get_type(), values.len() as u64);\n        self.context.new_rvalue_from_vector(None, typ, values)\n    }\n\n    fn const_to_opt_uint(&self, _v: RValue<'gcc>) -> Option<u64> {\n        // FIXME(antoyo)\n        None\n    }\n\n    fn const_to_opt_u128(&self, _v: RValue<'gcc>, _sign_ext: bool) -> Option<u128> {\n        // FIXME(antoyo)\n        None\n    }\n","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_codegen_gcc/src/common.rs#L284-L320","documentation":"`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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet struct_type = typ.is_struct().expect(\"struct type\");\nself.context.new_struct_constructor(None, struct_type.as_type(), None, values)\n\n// after (diagnose instead of asserting blindly)\nlet struct_type = typ.is_struct().unwrap_or_else(|| {\n    panic!(\"const_struct: type_struct did not yield a struct (kind={:?}, fields={}, packed={})\",\n        typ, values.len(), packed);\n});\nself.context.new_struct_constructor(None, struct_type.as_type(), None, values)","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// common.rs:302 -> typ.is_struct().expect(\"struct type\") inside const_struct.\n// Narrow before constructing so a mismatch yields a Result, not a panic.\nfn safe_const_struct<'gcc>(\n    cx: &CodegenCx<'gcc, '_>,\n    values: &[RValue<'gcc>],\n    packed: bool,\n) -> Option<RValue<'gcc>> {\n    let fields: Vec<_> = values.iter().map(|v| v.get_type()).collect();\n    let typ = cx.type_struct(&fields, packed);\n    let struct_type = typ.is_struct()?;\n    Some(cx.context.new_struct_constructor(None, struct_type.as_type(), None, values))\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["rustc-codegen-gcc","codegen","struct","type","panic","option-expect"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}