C named primitive types (ADR-0086)

The C named primitive types are thirteen built-in type names introduced by ADR-0086: c_schar, c_short, c_int, c_long, c_longlong, c_uchar, c_ushort, c_uint, c_ulong, c_ulonglong, c_float, c_double, and c_void. They are gated behind the c_ffi_extras preview feature.

The twelve arithmetic C named types are target-resolved. On every currently-blessed target (x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, aarch64-apple-darwin — all LP64), the resolutions are:
Gruel typeC typeWidth (bits)Signed
c_scharsigned char8yes
c_ucharunsigned char8no
c_shortshort16yes
c_ushortunsigned short16no
c_intint32yes
c_uintunsigned int32no
c_longlong64yes
c_ulongunsigned long64no
c_longlonglong long64yes
c_ulonglongunsigned long long64no
c_floatfloat32
c_doubledouble64

Each C named arithmetic type is distinct from every native Gruel arithmetic type and from every other C named type. A value of one cannot appear in a context that expects another without an explicit as conversion.

Integer literals coerce to a C named integer type when the context fixes one (for example a let annotation or a function return type). Float literals coerce to c_float or c_double analogously. The literal must fit the target-resolved width of the type.

All twelve C named arithmetic types are permitted across the FFI boundary (parameters of, and returns from, @mark(c) fn declarations and items inside link_extern blocks).

c_void is an incomplete type. It has no values, no size, and no alignment. A c_void name is well-formed only when it appears as the pointee of Ptr(c_void) or MutPtr(c_void). Bare c_void as the type of a let binding, function parameter, function return, struct field, or enum variant field is a compile-time error.

Ptr(c_void) and MutPtr(c_void) are permitted across the FFI boundary and elsewhere a raw pointer type is allowed. They correspond to C const void * and void *, respectively.
link_extern("c") {
    fn abs(x: c_int) -> c_int;
    fn malloc(size: usize) -> MutPtr(c_void);
    fn free(p: MutPtr(c_void)) -> ();
}

fn main() -> i32 {
    let x: c_int = 42;
    let p: MutPtr(c_void) = malloc(64);
    free(p);
    let y: c_int = abs(x);
    0
}