From 5684416ca5b325e2ead882b58a9ea6e2664a25fd Mon Sep 17 00:00:00 2001 From: Rua Date: Thu, 18 Jun 2026 13:19:45 +0200 Subject: [PATCH] transpile: Ensure that there are always types for primitive type kinds --- c2rust-transpile/src/c_ast/conversion.rs | 22 ++++++++++++++++++++++ c2rust-transpile/src/c_ast/mod.rs | 17 ++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/c2rust-transpile/src/c_ast/conversion.rs b/c2rust-transpile/src/c_ast/conversion.rs index 4a3acb0725..a36ce8fe26 100644 --- a/c2rust-transpile/src/c_ast/conversion.rs +++ b/c2rust-transpile/src/c_ast/conversion.rs @@ -503,6 +503,28 @@ impl ConversionContext { self.visit_node(untyped_context, node_id, new_id, expected_ty) } + // Check what primitive kinds were emitted by the compiler. + let mut found_kinds: HashMap<_, _> = CTypeKind::PRIMITIVE_KINDS + .into_iter() + .map(|kind| (kind, false)) + .collect(); + + for Located { kind, .. } in self.typed_context.c_types.values() { + if let Some(is_found) = found_kinds.get_mut(kind) { + *is_found = true; + } + } + + // If any primitives are missing, add them ourselves. + for (kind, is_found) in found_kinds { + if !is_found { + let new_id = self.id_mapper.fresh_id(); + self.add_type(new_id, not_located(kind)); + self.processed_nodes + .insert(new_id, self::node_types::OTHER_TYPE); + } + } + // Function declarations' types look through typedefs, but we want to use the types with // typedefs intact in some cases during translation. To ensure that these types exist in the // `TypedAstContext`, iterate over all function decls, compute their adjusted type using diff --git a/c2rust-transpile/src/c_ast/mod.rs b/c2rust-transpile/src/c_ast/mod.rs index 2b8a76e608..34946d14aa 100644 --- a/c2rust-transpile/src/c_ast/mod.rs +++ b/c2rust-transpile/src/c_ast/mod.rs @@ -2483,7 +2483,7 @@ pub struct AsmOperand { } /// Type qualifiers (6.7.3) -#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Hash)] pub struct Qualifiers { /// The `const` qualifier, which marks lvalues as non-assignable. /// @@ -2519,7 +2519,7 @@ impl Qualifiers { } /// Qualified type -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct CQualTypeId { pub qualifiers: Qualifiers, pub ctype: CTypeId, @@ -2546,7 +2546,7 @@ impl CQualTypeId { /// Represents a type in C (6.2.5 Types) /// /// Reflects the types in -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum CTypeKind { Void, @@ -2670,6 +2670,17 @@ pub enum CTypeKind { } impl CTypeKind { + /// Kinds for C primitive types. These are emitted by the compiler, but possibly only if + /// they are actually used in the code. + pub const PRIMITIVE_KINDS: [CTypeKind; 16] = { + use CTypeKind::*; + [ + Void, Bool, Char, SChar, Short, Int, Long, LongLong, UChar, UShort, UInt, ULong, + ULongLong, Float, Double, LongDouble, + ] + }; + + /// Kinds for Rust types that are pulled back into C, for more fine-grained translation. pub const PULLBACK_KINDS: [CTypeKind; 16] = { use CTypeKind::*; [