Fix Command¶
The fix command applies mechanical fixes to a fastC source file. Today it
runs the universal mechanical fix — fastc fmt — and exposes the
infrastructure for per-diagnostic structured fix-its from fastc check.
The Fix-it infrastructure (Fixit struct + applier) ships in v1.x; the
per-diagnostic backfill — wrap-in-unsafe, add-missing-use, missing-semicolon
suggestions — is incremental work landing one site at a time.
Usage¶
Arguments¶
| Argument | Description |
|---|---|
<INPUT> |
Input FastC source file (.fc) |
Options¶
| Option | Description |
|---|---|
--dry-run |
Print the diff to stdout without writing changes back |
--output-format <FORMAT> |
text (default) or json — the structured envelope |
-h, --help |
Print help |
Behavior¶
fastc fix runs the formatter pass over the input and compares the result
with the on-disk text:
- If the file is already up-to-date, prints
<path>: already up-to-date.to stderr and exits 0. - With
--dry-run, prints a unified-style line diff and exits 0 without touching the file. - Otherwise, overwrites the input file with the fixed text and prints
<path>: applied fixes.to stderr.
The JSON output format wraps the same operation in a structured envelope
that editor integrations and the MCP fix tool consume directly.
JSON Envelope¶
{
"status": "ok",
"applied": [
{
"label": "fmt: normalize whitespace",
"file": "src/main.fc",
"span": { "start": 0, "end": 42 }
}
],
"skipped": []
}
| Field | Type | Description |
|---|---|---|
status |
string | ok, noop, or error |
applied |
array | Per-fixit summary: human label, file path, byte span replaced |
skipped |
array | Fixits that overlapped or fell outside source bounds |
When the input is already canonical, the envelope reports
"status": "noop" with empty applied / skipped arrays.
Worked Example¶
A file with sloppy formatting (bad.fc):
Dry-run:
Output:
--- bad.fc
+++ bad.fc (after fastc fix)
- 1: fn add(a:i32,b:i32)->i32{return a+b;}
+ 1: fn add(a: i32, b: i32) -> i32 {
Applying the fix:
prints bad.fc: applied fixes. to stderr, and the file is now:
JSON envelope of the same run:
{
"status": "ok",
"applied": [
{ "label": "fmt: normalize source", "file": "bad.fc", "span": { "start": 0, "end": 37 } }
],
"skipped": []
}
How Structured Fix-its Work¶
The infrastructure lives in crates/fastc/src/fixit.rs. A Fixit carries
three things:
pub struct Fixit {
pub span: Span, // byte range to replace
pub replacement: String, // text to substitute (may be empty)
pub label: String, // human-readable description
}
apply_all sorts a batch by span end descending so earlier edits don't
shift later spans, then applies them in order. Overlapping fixits skip
the later one — the first wins. This means a diagnostic emitter can opt
into structured fixits by attaching Some(Fixit { ... }) to its
.with_help(...) site, and fastc fix will pick them up automatically.
When to Use It¶
- Pre-commit hook: drop
fastc fix --dry-runintopre-commitand fail the commit if formatting drifted. - Editor save-on-format: editors can invoke
fastc fix --output-format=jsonon save and apply the returned spans without re-reading the file. - CI gates: pair
fastc fix --dry-runwithfastc fmt --checkso the build catches both formatting drift and structured fix-it opportunities. - Agent loops: the MCP
fixtool wraps this command so an LLM can request a mechanical cleanup pass between diagnose / re-check cycles.
Limitations¶
- Today's universal fix is formatter-only. Per-diagnostic Fixits land incrementally — the v1.x infrastructure ships, the backfill follows.
apply_allis whole-file; the diff is line-aligned, not character- precise. For surgical edits, the MCPfixtool returns spans the editor can apply directly.
See Also¶
- Annotations — annotation surface the structured envelope reflects
- MCP Server — exposes
fixas an MCP tool over JSON-RPC - Compile — the
fastc fmtcompanion this command wraps