A compiler knows more about your program than it usually says. It proves facts, counts costs, and rewrites what its optimizers can reach — and then it keeps almost all of that to itself, because the only voices it has are the harsh ones: errors that stop you and warnings that judge you.

Mica 7.2.1 gives the compiler a third voice. Remarks are hints from its own knowledge about your code — be careful here, or do it another way — spoken only when you ask with --remarks, and never gating a build. The release ships together with VS Code extension 4.1.0, which puts that voice in the editor, and with the sqlite library — the first rung of the new libraries shelf, and the first user of the release’s other new arrival, the callback kind.

Remarks: what the compiler already knew

A remark exists where Mica is different by design and the difference is worth one sentence. The value model is the clearest case: values copy, honestly and visibly — and sometimes you did not want the copy. Ask, and the compiler says so:

$ mica --compile --remarks --source norm.mica --build build
Remarks:
    17: function Norm(sample : Sample) : int64;
                      ^ analyzer remark 5517 [17,15]: the parameter 'sample' copies its whole 32 bytes on every call, and this body only reads it: 'const sample : Sample' passes one address into caller-owned read-only storage instead — the same reading, with no copy at any call site

Six remarks ship at first light, and every one names its alternative in the sentence:

  • a by-value record wide enough that const changes the mechanism itself — one address instead of the bytes, with the byte count spelled;
  • a by-value dynamic array the body only reads, where a conformant view borrows the caller’s storage with no copy at any call site;
  • a string growing through its own + inside a loop, where every step copies everything built so far and a stringbuffer builds in place;
  • a whole wide record assigned name-to-name inside a loop — work through a pointer, or hoist the copy;
  • an indexed string walk under utf-8 at the debug tier, where for c in s reads the same code points in one pass;
  • an allocation inside a loop under the fixed-arena deployment class, where every iteration draws on a fixed budget.

Each speaker is deliberately narrow: it fires only where its sentence is true and its advice is a mechanical improvement — a body that writes its parameter, a copy outside any loop, a build where the optimizer already rewrites the walk all stay silent. Remarks are deterministic, they never repeat a rule the style documents own, and without the flag the compiler prints not one character more than before.

The flag is -rm | --remarks, it combines with every road including mica --run, and the command line reference carries its row.

The callback kind

The C world hands out its events through function pointers, and Mica does not have those: a routine is called with its argument list, never read by name, and every call graph stays static. Meeting libraries like sqlite honestly — sqlite3_exec fires a function pointer once per row — produced the third declared subprogram kind, beside task and generator:

callback CountRow(context : pointer Tally, columns : int32, values : pointer int64, names : pointer int64) : int32;
begin
    context.rows := context.rows + 1;
    CountRow := 0;
end;

rc := SqliteExecRaw(db, "select reading from m", CountRow, address tally, address sink);

A callback is never called from Mica and never a value. Its name stands in exactly one place — at a callback slot an imported contract declares — the foreign library performs every firing while the imported call runs, and the callback’s whole environment is the context record your call visibly hands over. Everything the callback can touch is on that one line, which is the same what-you-see-is-what-happens the value model promises everywhere else.

Callbacks at the boundary is the kind’s own chapter, and the contracts reference states the slot form a contract declares.

Libraries cross their contracts more completely

Two things a Mica library writes can now travel through its emitted contract whole:

  • An exported generator crosses as the source it is and compiles inside the importing program — so a library can ship a pull road, and for row in Rows(q) in your program reads like any local loop.
  • A borrowed handle keeps its borrowed pointer spelling across the boundary, so a library wrapping a C resource can answer handles the ownership analysis treats truthfully: your program owes no dispose for a cell the C side owns.

Both arrived because the sqlite library demanded them, which is what the libraries shelf is for: each rung meets a real library on its own terms, and what the meeting teaches flows back into the language. The notes application tutorial walks the whole road, and the sqlite announcement tells that story in full.

A handful of diagnostics also learned better manners in passing: sentences that once deferred to the future now state the rule on its own terms, with the actionable road named.

Extension 4.1.0: the voice in the editor

The extension pairs with the release and needs nothing configured — update the compiler, and remarks are simply there:

  • Remarks in the Problems panel, at the information severity, through the language server the extension already speaks.
  • A status-bar counter — a lightbulb that appears only when the open files carry remarks, clicking through to the Problems panel — and a mica.remarks.visible setting for a quiet session, errors and warnings never affected.
  • The snippet family returns, written against the current language: program and library skeletons, all three declared kinds — callback included — the concurrent block, the pull loop, on fail, records, error domains, case, and defer.
  • A new walkthrough step, Meet the remarks: paste one small program, save, and the compiler explains a copy you may not have wanted.
  • The grammar knows the callback word, arriving with the example that consumes it.

Getting it

The packages for both architectures are on the download page, the micalang/mica image ships 7.2.1 with the sqlite example inside, and the extension updates through your editor as 4.1.0. The changelog carries the release’s full error report — every new sentence the compiler can now say, remarks and refusals alike.

What is deliberately not here: remarks from the optimizing tiers themselves — facts like this guard is provably always true live behind the optimizer and wait for their own road — and the registered callback class, which a library stores and fires later, is declared but refuses every binding until it can be served on the task model’s own terms. Both are stated in their diagnostics rather than promised in prose.