Skip to content

Region Scopes

Overview

Region scopes manage lifetime through implicit region creation and destruction. All allocations made in a region are destroyed when that region exits. Region ownership is tracked by allocation provenance, not by lexical scope nesting.

Syntax

$ {
    let p = alloc Point;
    doSomething(p);
}

$ {
    let a = alloc Point;
    $ {
        let b = alloc Point;
        doSomething(b);
    }
}

extern ^ function makePoint(): &Point;

export function main(): int {
    $ {
        let p = makePoint();
        doSomething(p);
    }
}

Rules

Region Creation

Upon entering a $ { ... } scope, larol_region_create() MUST be called implicitly (which returns a opaque 64 bit region handle). The resulting region handle MUST be stored in a compiler-managed variable with an inaccessible internal name. This variable MUST NOT be referenceable by user code. If region creation fails, the runtime implementation will treat this as a fatal error.

Region Destruction

Directly before exiting a $ { ... } scope, larol_region_destroy(region) MUST be called implicitly. This applies to all exit paths including normal block exit, return, break, and continue. If region destruction fails, the runtime implementation will treat this as a fatal error.

Non-Empty Body

A region scope MUST contain at least one statement. An empty $ { } MUST NOT be permitted.

Nested Regions

Nested region scopes MUST be permitted. Direct access to handles allocated in an outer region MUST be permitted. Moving a handle from an outer lexical scope inside a nested region MUST be permitted if all move and lifetime constraints are satisfied. Nested regions MUST be destroyed in reverse order of creation.

Handle Lifetime

A handle MUST NOT outlive the region in which it was allocated. A handle MUST NOT be moved into storage that may outlive its allocation region. A handle allocated in an inner region MUST NOT be moved to an outer region, returned to a caller whose ambient region does not include that allocation, or otherwise exposed beyond its allocation region lifetime.

Handle-Containing Struct Lifetime

A struct type that transitively contains owned handles MUST follow the same region lifetime constraints as direct handle values. A value of such a type MUST NOT be moved into storage that may outlive any owned handle it contains. The compiler MUST enforce this constraint at compile time.

Region-Qualified Function Interaction

Region-qualified functions (^ function) MUST execute with a caller-provided ambient region context. A region-qualified function MAY return a value that transitively contains an owned handle only when every owned handle in the returned value originates from the caller ambient region context, not from a nested region created inside the callee.

Capability Lifetime

The compiler MUST ensure that no capability derived from a handle in a region is still active when that region is destroyed. Producing a capability that would outlive its source region MUST be a compile-time error.