Skip to content

Raw output uses unstable features/idioms that don't survive a real kernel-embedded build (extern_types, missing unsafe{} blocks, .init_array trick) #20

Description

@awto-au

Summary

First real attempt to wire c2rust's raw, "clean"-outcome output directly into a real kernel build (not just standalone rustc --crate-type lib compile-checking) found three genuine, corpus-wide gaps between "c2rust says clean" and "actually compiles/links in a real kernel context." Full evidence and fix details: docs/combined-boot-attempt-2026-07-18.md in the linux-rs repo.

Test case: lib/group_cpus.cgroup_cpus_evenly(), chosen because it was already c2rust-clean and passed every rule-conformance check this project has. Despite that, it needed real hand-fixes before it would compile as part of an actual kernel build (scripts/Makefile.build's real Rust compilation path, not a standalone rustc invocation).

Gap 1: unstable features outside the kernel's allowed set

c2rust's raw output declared #![feature(asm, extern_types, raw_ref_op, strict_provenance)]. Real kernel builds (this one, and by inspection the general Rust-for-Linux convention — see Rust-for-Linux/linux#2) hard-restrict which unstable features non-rust/-crate code may use via -Zallow-features=... plus a -Zcrate-attr='feature(...)' override that replaces any file-level #![feature(...)] declaration entirely. This project's allowed set: arbitrary_self_types,asm_goto,generic_arg_infer,used_with_arg — zero overlap with what c2rust emitted.

Concretely, the biggest offender is extern_types, used for every pulled-in-from-headers opaque type marker (extern "C" { pub type foo; }) — c2rust emits dozens of these per file for types the actual translated function never even uses (whole-TU header context, not per-function scoping). A stable substitute exists and was used successfully in this fix: a zero-field #[repr(C)] struct foo { _private: [u8; 0] } gives the same "opaque, pointer-only" semantics without the unstable feature.

Gap 2: missing explicit unsafe {} blocks inside unsafe fn bodies

26 raw pointer dereferences / unsafe-function calls inside unsafe extern "C" fn bodies had no explicit unsafe {} wrapper — c2rust relies on older implicit-unsafe-in-unsafe-fn semantics. This surfaced as E0133 errors in the real kernel build even under --edition=2021 (the kernel's own build flag), suggesting either a rustc-version-level default shift or an interaction with the crate-attribute override from Gap 1. Mechanical fix: wrap each affected function's body in one unsafe { ... } block.

Gap 3: .init_array constructor trick has no kernel-linker equivalent

c2rust emits a __UNIQUE_ID_addressable_* static plus a c2rust_run_static_initializers() function registered via #[link_section = ".init_array"], intended to keep a function's address alive against dead-code elimination in a userspace ELF-loader context (a libc/dynamic-linker convention). The kernel's own link script has no .init_array support and discards the section, leaving a dangling relocation: ld.lld: relocation refers to a symbol in a discarded section. Not needed in a kernel context where the real EXPORT_SYMBOL_GPL asm block already keeps the symbol referenced — likely safe to simply not emit this pattern at all for kernel-target output (or gate it behind a kernel-idiom rule, same mechanism as the existing --enable-rule conventions).

Ask

Each gap is corpus-wide (affects any file using these constructs, not just group_cpus.c) and mechanically fixable in the transpiler:

  1. Avoid emitting extern_types for unused opaque-type declarations (or use the zero-field-struct idiom generally instead of extern type).
  2. Wrap raw unsafe operations in unsafe-fn bodies in explicit unsafe {} blocks.
  3. Don't emit the .init_array constructor pattern (or gate it behind an opt-in rule, off by default for kernel targets).

Filed with concrete evidence from a real fix, not a hypothetical — happy to share the full hand-fixed file as a reference if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions