Skip to content

Raw native source

raw is the final interop escape hatch. Inside the body you are writing the selected native language, not unchecked Z.

const observed = raw c
using (in left, inout right, out output)
: i32 {
*right += *left;
*output = *right;
return *output;
};

The compiler lowers this expression to an isolated helper. The using clause is the complete audited boundary between surrounding Z storage and the native body.

Capture Native permission
in value Read the borrowed input
inout value Read and replace caller storage
out value Initialize previously uninitialized caller storage

Every lexical Z value used by the body must appear in using. out must be initialized on every successful helper path, and its binding becomes readable after the raw expression completes.

The first tier accepts ABI-stable scalars, cstring, and imported native types. It rejects move captures and Z-owned representations whose native lifetime cannot be described by this small helper boundary.

The helper is an important semantic boundary:

function calculate(left: i32, right: i32): i32 {
const answer = raw c using (in left, in right): i32 {
return *left + *right;
};
return answer;
}

The first return exits the generated C helper. It cannot skip Z cleanup or return from calculate. Surrounding owners remain under ordinary Z lifetime rules.

When the function signature already describes the complete boundary, use a raw function body:

function add(left: i32, right: i32): i32 = raw c {
return left + right;
}
function nativeCount(input: i32): i32 = raw cpp {
return static_cast<int32_t>(input);
}

Objective-C bodies use the same form and may retain an explicit main-executor contract:

function activateNative(): i32 on thread.main = raw objc {
// Objective-C source
return 0;
}

The supported tags are c, cpp, and objc. Async, throwing, generic, and method raw bodies remain outside the current tier.

For an in Objective-C reference, the native parameter is the object pointer, not a pointer to its ARC storage slot. This remains true for a stored-reference argument such as in resource.file or in this.file during deinit. Scalar and value borrows still pass storage addresses. This fixes a representation boundary; it does not allow arbitrary native property projections or change Z class aliasing rules.

Owned Z structs containing Objective-C references also compose with Option and throwing results. Both compiler paths choose ARC-compatible payload storage: nested strong-reference payloads use separate slots rather than an illegal C union. This requires no heap box, though an enum with multiple such payload alternatives can be larger than a union.

Stage 0 and the fixed-point native compiler preserve the body verbatim, map native diagnostics back to this .zs location, and include native headers explicitly imported by the containing module. A header remains available even when the raw body is its only consumer.

The Z editor extension embeds the platform C, C++, or Objective-C TextMate grammar inside both named and anonymous raw bodies. Nested native braces remain inside the embedded language, while Z semantic tokens stop at the raw-source boundary. Native completion, hover, and go-to-definition are a later Clang-backed editor tier; highlighting does not imply that Z has type-checked the body.

The generated translation unit already includes imported headers. Their functions, constants, macros, records, unions, and native language features are available to the appropriate compiler even when Z cannot model them.

The raw body cannot reference compiler-generated private symbols. Legitimate header names—including libraries whose public constants begin with Z_—remain valid; the compiler rejects actual generated-name collisions rather than claiming a broad vendor prefix.

Native diagnostics are mapped back to the original .zs location. This is essential: the generated translation unit is an implementation artifact, not the source developers should debug.

Need Use
A supported header declaration Direct import
Reusable ownership, cleanup, callback, error, or lifetime facts .zd
One local typed interpretation of a native value unsafe
Native syntax or a type-system escape raw c/cpp/objc

Raw source should remain visibly less convenient than the checked path. If a pattern recurs, it is evidence that the importer or .zd vocabulary should grow.

Runnable example: raw native boundary.

Next: Objective-C interop.