Built-in Types Reference

This page documents every built-in type constructor, enum, and interface the Gruel compiler hard-codes by name. ADR-0081 retired the BUILTIN_TYPES registry; built-in types (currently just String) live in the prelude alongside Option / Result. The constructors, enums, and interfaces here are still hard-wired because their semantics aren't expressible as ordinary Gruel code.

Quick Reference

Type Constructors

NameArityDescription
Ptr1immutable raw pointer (ADR-0061)
MutPtr1mutable raw pointer (ADR-0061)
Ref1immutable reference (ADR-0062)
MutRef1mutable reference (ADR-0062)
Slice1immutable slice (ADR-0064)
MutSlice1mutable slice (ADR-0064)
Vec1owned, growable vector (ADR-0066)

Enums

Platform-reflection enums (Arch, Os) live in prelude/target.gruel; type-reflection enums (TypeKind, Ownership) live in prelude/type_info.gruel. The corresponding intrinsics produce values of these types by name lookup.

NameVariants
ArchX86_64, Aarch64, X86, Arm, Riscv32, Riscv64, Wasm32, Wasm64
OsLinux, Macos, Windows, Freestanding, Wasi
TypeKindStruct, Enum, Int, Bool, Unit, Never, Array
OwnershipCopy, Affine, Linear
ThreadSafetyUnsend, Send, Sync

Interfaces

Compiler-recognized interfaces are declared in prelude/interfaces.gruel. The compiler keys off these names for hardcoded behaviors (drop glue, @derive(Clone) synthesis, Handle linearity carve-out). ADR-0080 retired Copy from this set: posture is declared on the type with the copy keyword and queried via @ownership(T).

NameMethodConformance
Dropfn __drop(self)method presence
Clonefn clone(self: Ref(Self)) -> Self@derive(Clone)
Handlefn handle(self: Ref(Self)) -> Selfmethod presence

Markers

Marker names recognized inside the @mark(...) directive (ADR-0083). Markers attach declaration-time metadata to a struct/enum head; future markers plug in by adding a row to the BUILTIN_MARKERS registry.

NameKindApplies to
copyPosture(Copy)struct or enum
affinePosture(Affine)struct or enum
linearPosture(Linear)struct or enum
unsendThreadSafety(Unsend)struct or enum
checked_sendThreadSafety(Send)struct or enum
checked_syncThreadSafety(Sync)struct or enum
cAbi(C)(none)
uncheckedUncheckedfn only

Type Constructors

Built-in type constructors are written Name(arg1, arg2, ...) in type position. Sema resolves the name against the registry and lowers directly to a TypeKind without running the comptime interpreter.

Ptr(T)

immutable raw pointer (ADR-0061).

MutPtr(T)

mutable raw pointer (ADR-0061).

Ref(T)

immutable reference (ADR-0062).

MutRef(T)

mutable reference (ADR-0062).

Slice(T)

immutable slice (ADR-0064).

MutSlice(T)

mutable slice (ADR-0064).

Vec(T)

owned, growable vector (ADR-0066).

Enums

Platform-reflection (Arch, Os) and type-reflection (TypeKind, Ownership) enums. Declarations live in prelude/target.gruel and prelude/type_info.gruel respectively; the corresponding intrinsics (@target_arch, @target_os, @type_info, @ownership) materialize values of these types.

Arch

IndexVariant
0Arch::X86_64
1Arch::Aarch64
2Arch::X86
3Arch::Arm
4Arch::Riscv32
5Arch::Riscv64
6Arch::Wasm32
7Arch::Wasm64

Os

IndexVariant
0Os::Linux
1Os::Macos
2Os::Windows
3Os::Freestanding
4Os::Wasi

TypeKind

IndexVariant
0TypeKind::Struct
1TypeKind::Enum
2TypeKind::Int
3TypeKind::Bool
4TypeKind::Unit
5TypeKind::Never
6TypeKind::Array

Ownership

IndexVariant
0Ownership::Copy
1Ownership::Affine
2Ownership::Linear

ThreadSafety

IndexVariant
0ThreadSafety::Unsend
1ThreadSafety::Send
2ThreadSafety::Sync

Interfaces

Compiler-recognized interfaces. Declarations live in prelude/interfaces.gruel; the compiler keys off the interface names for hardcoded behaviors. Conformance is structural — a type satisfies the interface when it provides matching methods.

Drop

Types with custom cleanup logic that runs when the value goes out of scope (ADR-0059).

Required methods:

  • fn __drop(self)

Conformance: structural (no derive). Defining fn __drop(self) on a struct or enum makes it conform — there is no @derive(Drop) directive.

Clone

Types that may be explicitly duplicated via .clone(). All Copy types auto-conform (ADR-0065).

Required methods:

  • fn clone(self: Ref(Self)) -> Self

Conformance derive: @derive(Clone) (compiler-recognized; no user derive declaration required). Synthesizes a clone method that recursively calls clone on every field (struct) or variant payload (enum). Synthesis fails if any field is not Clone. Rejected on linear types.

Handle

Types that may be explicitly duplicated via .handle(), typically because the duplication has visible cost (refcount bumps, transaction forks). Unlike Clone, Handle is permitted on linear types (ADR-0075).

Required methods:

  • fn handle(self: Ref(Self)) -> Self

Conformance: structural (no derive). Defining fn handle(self: Ref(Self)) -> Self on a struct or enum makes it conform — there is no @derive(Handle) directive.

Markers

Markers are declaration-time-only attributes on struct/enum heads, written inside @mark(...) (ADR-0083). The marker set is closed; user-defined markers are out of scope. New markers must go through an ADR.

@mark(copy)

Asserts the type is Copy. Under uniform structural inference, a struct/enum of all-Copy fields would already be Copy without the directive — @mark(copy) exists so the user can document intent and turn a silent posture downgrade (adding a non-Copy field later) into a declaration-site error.

@mark(affine)

Suppresses Copy inference. A type whose members would otherwise infer Copy is forced to remain Affine, so move-on-use semantics are preserved even when bitwise duplication is safe. Has no effect on Linear inference: a Linear member still propagates upward.

@mark(linear)

Forces the type to be Linear regardless of member postures. Use when the type has linear semantics that are not visible from its fields (e.g. an i32 handle that is actually a kernel resource ID).

@mark(unsend)

Downgrades the type's thread-safety classification to Unsend, even if its members would structurally permit Send or Sync. Always safe — the marker only restricts. Use when the type has thread-affine state that isn't visible from its fields (e.g. a handle to a thread-local resource).

@mark(checked_send)

Asserts the type is Send, even if a member's type would structurally pull it down to Unsend (e.g. a raw pointer field). The compiler cannot verify this — the checked_ prefix flags it as a user assertion (analogous to Rust's unsafe impl Send). Mis-applying breaks data-race freedom; the user takes responsibility.

@mark(checked_sync)

Asserts the type is Sync, even if its structural minimum would be Send or Unsend. The compiler cannot verify this — the checked_ prefix flags it as a user assertion (analogous to Rust's unsafe impl Sync). Mis-applying breaks data-race freedom; the user takes responsibility.

@mark(c)

Selects the C ABI / C layout (ADR-0085). On a function, uses the platform C calling convention and suppresses Gruel name mangling. On a struct, switches to C field layout (declaration order, natural alignment, no reordering, niches disabled), making the type eligible to cross the FFI boundary by value.

@mark(unchecked)

Declares a fn (top-level, method, interface method, or FFI import) as unchecked (ADR-0088). Every caller must wrap the call in a checked { } block; the body's soundness rests on a caller-asserted precondition the type system can't verify. Replaces the legacy unchecked keyword and extends the surface to methods, interface method signatures, and FFI imports under a single uniform spelling.