This page documents the current limitations of Forge’s first milestone. Some features are parsed or type-checked but do not work end-to-end. Everything here is expected to land in future milestones.
These constructs are rejected with a clean diagnostic instead of panicking the compiler:
| Construct | Error |
|---|---|
impl blocks: impl Point: ... |
Supported — obj.method(args) desugars to Point::method with the receiver as the first argument; generic impls (impl Pair[T]:) and generic methods are monomorphized per call site |
Nested struct fields: Outer { inner: Inner { ... } } |
Supported; layouts are computed recursively |
Recursive structs by value: struct A: a: A |
struct \A` contains itself by value` |
int128 / uint128 |
128-bit integers are not supported by any backend yet |
std.gc on x86_32 |
`_dev_gc_collect` (std.gc) is not supported on the x86_32 target; std.alloc's alloc/free work, but there is no garbage collector (at codegen) |
| Construct | Status |
|---|---|
union |
“not a struct type” error; no codegen |
| Tuples | Supported end-to-end on x86_64 and x86_32: literals, annotations, indexed field access, destructuring, return types, and destructuring tuple-typed params |
Generic signatures with union types |
Lowering error — union types are not supported in generic signatures yet |
Generic enum E[T] |
Supported end-to-end (monomorphized per instantiation; Opt[int64] -> Opt$i64 / __enum_Opt$i64) |
@c_enum |
Supported — enum Color with @c_enum is lowered as i32 integer constants (no struct layout) |
Default type parameters [T, U = int32] |
Supported — omitted trailing arguments are filled from their defaults on structs, enums, and functions/methods |
Struct update ..base |
Supported — Point { x: 1, ..base } copies missing fields from base |
Fixed-size array annotations [int32; 5] and repeat literals [0; 3] |
Supported end-to-end on x86_64 and x86_32: [T; N] types and [expr; N] repeat literals (element-wise StackAlloc + scaled ptr+idx stores) |
Slices slice[T], &arr[..], &arr[1..3] |
Supported (slicing yields Slice, lowers to offset pointer; full ptr+len struct is TODO) |
Function types fn(int32) -> int32 |
Supported at type level (lowers to Ptr; direct calls work, indirect calls via fn values are TODO) |
refmut[T] / &mut x |
Supported (&mut → RefMut, indexes like pointers; borrow checking is TODO) |
own[T] |
Supported as Ptr (indexes like pointers; ownership checking is TODO) |
Byte-string literals b"bytes" / b'c' |
Supported end-to-end (ptr[u8] decay, \xNN escapes) |
Block expressions let x = { ... } |
Supported end-to-end |
@export, @inline, @noreturn, @naked |
Accepted (codegen hints are TODO) |
@packed, @align(N) |
Honored in struct layout (x86_64/x86_32/x86_16) |
@c_enum |
Honored — C-like enums are plain i32 constants |
Compound assignment +=, -=, etc. |
Supported end-to-end (desugar x += 1 to x = x + 1; see Syntax) |
asm!() |
Compile-time error on all targets — inline assembly is intentionally not supported (the parser accepts the syntax for forward compatibility only); use the std.hal module’s port-I/O, interrupt, and PIC wrappers instead |
as (or any expression) is never merged with a
following statement that starts with (, [, or { — those can begin a new
statement. Multi-line continuation still works for . and as at the same
indentation.float32/float64 usage fails at
codegen. Stdlib modules that use floats cannot be imported on x86_32.__enum_* structs are the exception — their values are 4-byte
pointers and keep scalar semantics everywhere.-O0 quality.--freestanding is required for x86_16-boot programs; hosted runtime
helpers (_dev_puts, _dev_exit, …) are only emitted for hosted targets.std.gc is x86_64 only — importing it on x86_32 fails at codegen with a
clean diagnostic (the free-list allocator works, there is just no
collector).std.alloc on x86_32 is a free-list allocator (first-fit with splitting,
4-byte block headers); free returns blocks to the list for reuse, but
there is no automatic reclamation.std.string functions require null-terminated strings; no bounds checking.getchar returns -1 on EOF; rand is a 31-bit LCG (not cryptographic).std.* module compiles the entire module file, so importing
a module that uses float64 on x86_32 will fail.mymodule.foo()) is not supported.std.* and local .dev modules are supported.forgec builds and runs on Linux x86_64 (and i686 hosts for x86_32
output). macOS and Windows targets are planned but not implemented.qemu-system-x86_64) to run.