Read-Only Sharing: Shared<T>

Shared lets several parts of your program read the same data without copying it, and without giving any of them the ability to change it. It’s the most common way to pass arrays, objects, and strings between functions when you only need to look at them.

Key benefits

  1. No copying. For larger data like arrays, the data stays in one place — Cuttlefish passes a read-only view rather than making a duplicate.
  2. Truly read-only. Unlike an ordinary TypeScript const, Shared also locks the contents — so you can’t quietly change an array element either.

Safety Enforcements

Error: ownership-assign-to-ref

A Shared variable is strictly read-only. You cannot reassign the variable or update its value.

function demo(x: Shared<number>) {
  x = 10; // ERROR: Cannot assign to 'x' — it is an immutable borrow.
  x++;    // ERROR: Cannot update 'x' — it is an immutable borrow.
}

How to fix: If you need to modify the data, change the annotation to Mut.


Lifetime and Scope

Because a Shared is a “borrow,” the data it points to must stay alive as long as the Shared exists.

Error: ownership-dangling-borrow

Occurs when a Shared in an outer scope points to an Owned variable in a inner scope that is about to be destroyed.

let saved: Shared<Uint8Array>;
{
  const local: Owned<Uint8Array> = new Uint8Array([1]);
  saved = local; // ERROR: 'saved' borrows 'local' which goes out of scope here.
}
// 'saved' is now a dangling pointer in C++

Error: ownership-return-local-ref

Occurs when you try to return a Shared that points to data created inside the function.

function view() {
  const local: Owned<Uint8Array> = new Uint8Array([1]);
  return local; // ERROR: Returning 'local' which will be destroyed.
}

Memory Warnings

Warning: ownership-temp-ref-warn

C++ cannot bind a reference to a temporary value (rvalue). If you initialize a Shared directly from a literal or a constructor, the emitter will fall back to a copy.

const view: Shared = new Uint8Array([1, 2, 3]); 
// WARNING: 'view: Shared' borrows a temporary — emitter will fall back to a copy.

How to fix: Declare an Owned variable first, then borrow from it:

const storage: Owned = new Uint8Array([1, 2, 3]);
const view: Shared = storage; // Safe zero-copy borrow

Info: ownership-implicit-copy

If you copy a Shared variable into a variable with no annotation, Cuttlefish warns you that you are creating a copy of the underlying data rather than a new reference.

const src: Shared<Uint8Array> = ...;
const dup = src; // INFO: 'dup' silently copies 'src' — no borrow annotation.

API Summary

FeatureDescription
ImmutabilityPrevents all writes, including element access (e.g., arr[0] = 1).
C++ EmissionEmits const T& for complex types, const T for primitives.
Zero-CopyGuarantees no data is duplicated when passed to functions.