Skip to content
GUIDES

Opaque objects and private library state

RFC 0028 preserves supported inferred contracts when a client’s public header contains only struct node; or struct buffer;. Analyze the implementation and client together, or compile both with weavec-cc and select the client at link time:

Terminal window
weavec --whole-program --checked-function=main client.c library.c -- -std=c11
weavec-cc -c library.c -o library.o
weavec-cc -c client.c -o client.o
weavec-cc -fweavec-checked-function=main client.o library.o -o client

A verified constructor supplies the object’s actual allocation and initialized shape. That evidence follows pointer copies, supported returned borrows and ownership transfers. Forwarding helpers can export sufficient input predicates; a closed client must discharge them. A forward declaration, cast or matching layout alone supplies no ownership or memory permission. Double destruction, lost detached ownership and use of a saved borrow after destruction remain failures.

Returned buffers carry their verified initialized-prefix relation and captured capacity bounds. Successful append can establish initialized elements; a failed append or an increased capacity does not initialize additional bytes. Accessors retain the backing allocation’s identity, including when called directly in an indexing expression. Replacing or releasing storage invalidates saved borrows.

Private setters and initializers transport actual scalar and callback state. Separate modules’ same-spelled static variables stay distinct. An established callback target uses its analyzed implementation or existing modeled libc contract; unknown or nullable targets cannot acquire a contract from their prototype. Writes invalidate dependent state. Callers cannot assume an initializer still describes storage after reachable mutations.

The pinned cJSON public-header clients establish default or concrete custom hooks and verify supported lifecycle operations with its unchanged implementation in a separate source unit. For compiler-object builds, request an unselected contract report while compiling the library, then select the client at link:

Terminal window
weavec-cc -fweavec-checked-report=library-contracts.json -c cJSON.c -o cJSON.o
weavec-cc -c client.c -o client.o
weavec-cc -fweavec-checked-function=main client.o cJSON.o -o client

An unselected compile report collects contracts without claiming that the whole library checks. The selected link must still discharge every client obligation.

Portable descriptions support ordinary scalar types, pointers, C function types, structs and fixed arrays, including cyclic pointer layouts. They are bounded to 128 type nodes, 64 fields per record and 64 KiB per description. Unions, bitfields, atomic/volatile access, flexible arrays, variable-length storage and exhausted limits can prevent complete inference. These descriptions preserve layout; they do not imply that every operation on a supported type is provable. General shared graphs and asynchronous callback protocols remain outside this milestone.

The metadata remains internal to analysis. It neither completes the client’s forward declarations nor inserts private names into C lookup. Conflicting layouts lose evidence. Rebuild older artifacts: summary format 23, sidecar format 24 and checkpoint format 3 intentionally reject previous artifacts. Source/header, preprocessing, target and object-content validation still apply; this does not support source-free checked linking.