# Sway — Administrator & Developer Guide

> **Audience:** Compiler engineers, toolchain contributors, language designers,
> blockchain infrastructure operators, and advanced integrators building on the
> Fuel ecosystem.

---

## Table of Contents

1. [Architecture Overview](#1-architecture-overview)
2. [System Requirements](#2-system-requirements)
3. [Configuration Reference](#3-configuration-reference)
4. [Deployment & Scaling](#4-deployment--scaling)
5. [Operations](#5-operations)
6. [Performance](#6-performance)
7. [Security](#7-security)
8. [Developer Internals](#8-developer-internals)
9. [Integration Points](#9-integration-points)

---

## 1. Architecture Overview

Sway is a domain-specific programming language targeting the FuelVM — the
virtual machine powering the Fuel blockchain. It is syntactically and
semantically inspired by Rust, providing ownership semantics, type inference,
pattern matching, and generics, while being specifically designed for the
constraints and capabilities of a UTXO-based blockchain execution environment.

The repository is a large Rust workspace (`Cargo.toml` at root) containing the
complete Sway toolchain: compiler, formatter, language server, package manager,
documentation generator, debugger, and migration assistant. Version **0.71.0**,
source commit **e12e611**, spanning **8,121 files**.

> [!NOTE]
> The entire Sway toolchain — compiler, package manager, LSP, formatter, and
> CLI — is developed as a single Rust workspace. All crates share a unified
> dependency tree, enabling cross-crate type sharing without serialization
> overhead. The `forc` CLI binary is the single user-facing entry point into
> this ecosystem.

### 1.1 Workspace Members

| Crate | Path | Role |
|-------|------|------|
| `forc` | `forc/` | CLI entry point, subcommand dispatcher |
| `forc-pkg` | `forc-pkg/` | Package manager, dependency resolution, build plans |
| `forc-test` | `forc-test/` | Test framework runner |
| `forc-util` | `forc-util/` | Shared CLI utilities, bytecode parsing |
| `forc-debug` | `forc-plugins/forc-debug/` | DAP debug server |
| `forc-doc` | `forc-plugins/forc-doc/` | HTML documentation generator (swaydoc) |
| `forc-fmt` | `forc-plugins/forc-fmt/` | Formatter CLI frontend |
| `forc-lsp` | `forc-plugins/forc-lsp/` | LSP server wrapper |
| `forc-migrate` | `forc-plugins/forc-migrate/` | Breaking-change migration assistant |
| `forc-publish` | `forc-plugins/forc-publish/` | Package registry publisher |
| `forc-tx` | `forc-plugins/forc-tx/` | Transaction builder |
| `sway-ast` | `sway-ast/` | AST data structures for all language constructs |
| `sway-core` | `sway-core/` | Core compiler: type checking, IR gen, ASM gen |
| `sway-error` | `sway-error/` | Error and warning type definitions, handler |
| `sway-features` | `sway-features/` | Experimental feature flag management |
| `sway-ir` | `sway-ir/` | SSA-form intermediate representation |
| `sway-ir/sway-ir-macros` | `sway-ir/sway-ir-macros/` | Proc-macros for IR construction |
| `sway-lsp` | `sway-lsp/` | LSP implementation (capabilities + server loop) |
| `sway-parse` | `sway-parse/` | Lexer and recursive-descent parser |
| `sway-types` | `sway-types/` | Shared types: spans, identifiers, source maps |
| `sway-utils` | `sway-utils/` | Utility functions, manifest discovery, constants |
| `swayfmt` | `swayfmt/` | Code formatter library |
| `test` | `test/` | E2E, snapshot, and in-language test harness |
| `mdbook-forc-documenter` | `scripts/mdbook-forc-documenter/` | mdBook plugin for forc docs |

### 1.2 High-Level Data Flow

```
┌─────────────────────────────────────────────────────────────────────┐
│                          forc build                                 │
│                       (CLI entry point)                             │
└───────────────────────────┬─────────────────────────────────────────┘
                            │
                    ┌───────▼────────┐
                    │   forc-pkg     │
                    │  Manifest parse│
                    │  Dep resolve   │
                    │  Build plan    │
                    └───────┬────────┘
                            │ per-package source files
              ┌─────────────▼──────────────┐
              │        sway-parse          │
              │  Lex → Token stream        │
              │  Parse → sway-ast nodes    │
              └─────────────┬──────────────┘
                            │ parsed AST
              ┌─────────────▼──────────────┐
              │        sway-core           │
              │  Type checking             │
              │  Declaration engine        │
              │  Control flow analysis     │
              └─────────────┬──────────────┘
                            │ typed AST
              ┌─────────────▼──────────────┐
              │        sway-ir             │
              │  IR generation (SSA)       │
              │  Optimization passes       │
              └─────────────┬──────────────┘
                            │ optimized IR
              ┌─────────────▼──────────────┐
              │        sway-core           │
              │  ASM generation            │
              │  Virtual → Allocated → Final│
              └─────────────┬──────────────┘
                            │
              ┌─────────────▼──────────────┐
              │        Output              │
              │  Bytecode (.bin)           │
              │  ABI (.json)               │
              │  Debug info                │
              └────────────────────────────┘
```

### 1.3 Program Types

Sway supports four distinct program types, each with different execution
semantics and structural requirements:

| Program Type | Entry Point | Return Type | Purpose |
|---|---|---|---|
| `contract` | ABI function dispatch | `()` per function | Deployed smart contract; has storage, ABI |
| `script` | `main()` | Any | Executed once per transaction; no persistent storage |
| `predicate` | `main()` | `bool` | Authorization; pure function; no storage |
| `library` | (module root) | N/A | Reusable code; no entry point |

The program type is declared at the top of every Sway file:

```sway
contract;   // or: script; predicate; library;
```

### 1.4 Plugin System Architecture

The `forc` binary implements an extensible plugin system: any binary named
`forc-<name>` found on `PATH` is automatically discovered and exposed as
`forc <name>`. This allows third-party plugins without modifying `forc` itself.

```
forc <cmd>
  ├── Built-in subcommands (new, build, check, clean, deploy, run, ...)
  └── forc-* on PATH (forc-debug, forc-doc, forc-fmt, forc-lsp, ...)
```

Plugin discovery uses `which`-style PATH scanning at runtime. Each plugin
binary receives forwarded arguments and inherits the calling environment.

### 1.5 Build Targets

| Target | Description |
|---|---|
| `fuel` | Default; targets FuelVM bytecode via `fuel-asm` / `fuel-vm` |
| `evm` | Targets EVM bytecode via the EVM ABI and code generation path |

---

## 2. System Requirements

### 2.1 Build Dependencies

| Dependency | Version | Purpose |
|---|---|---|
| Rust toolchain | Stable (pinned in `rust-toolchain.toml`) | Compile the workspace |
| `just` | >= 1.0 | Task runner (project-wide recipes) |
| `cargo` | Bundled with Rust | Build and test |
| `git` | >= 2.0 | Source control, forc-pkg git dependencies |
| `fuel-core` node | 0.48.x | Required for E2E and node-based tests |
| `forc` (bootstrapped) | 0.71.0 | Building Sway example projects |

### 2.2 Optional Build Dependencies

| Dependency | Purpose |
|---|---|
| `mdbook` | Building the Sway book |
| `cargo-nextest` | Faster parallel test execution |
| `cargo-sort` | Enforcing sorted `Cargo.toml` dependencies (CI) |
| `cargo-audit` | Security advisory scanning |
| `sccache` | Cross-invocation Rust compilation caching |

### 2.3 Runtime Requirements (forc)

| Requirement | Notes |
|---|---|
| `git` on PATH | Required for git-sourced dependencies in `Forc.toml` |
| Network access | For fetching remote dependencies (disable with `--offline`) |
| `fuel-core` node | Required for `forc run`, `forc deploy`, `forc test` E2E |
| Write access to `~/.forc/` | Cache directory for downloaded packages |

### 2.4 Platform Support

| Platform | Status |
|---|---|
| Linux x86_64 | Primary CI target; fully supported |
| macOS Apple Silicon | Supported; CI tested |
| macOS Intel | Supported |
| Windows x86_64 | Community supported; some path-handling edge cases |

### 2.5 Key Dependency Versions

| Crate | Version | Role |
|---|---|---|
| `fuel-vm` | 0.66 | FuelVM execution engine |
| `fuel-tx` | 0.66 | Fuel transaction types |
| `fuel-asm` | 0.66 | Fuel assembly instruction set |
| `fuels` | 0.77 | Fuel Rust SDK (SDK harness tests) |
| `fuel-core-client` | 0.48.0 | Fuel node GraphQL client |
| `clap` | 4.5 | CLI argument parsing |
| `tokio` | latest stable | Async runtime |
| `petgraph` | latest | Dependency DAG |
| `dashmap` | latest | Concurrent HashMap for LSP |
| `serde` / `serde_json` / `toml` | latest | Serialization |
| `lsp-types` | 0.94 | LSP protocol types |
| `tower-lsp` | 0.20 | LSP server framework |
| `horrorshow` | latest | HTML generation (forc-doc) |
| `tikv-jemallocator` | latest | Memory allocator (performance) |

---

## 3. Configuration Reference

### 3.1 Forc.toml — Package Manifest

`Forc.toml` is the package manifest, analogous to `Cargo.toml`. It is located
at the project root. The constant `MANIFEST_FILE_NAME = "Forc.toml"` is
defined in `sway-utils`.

#### `[project]` Section

```toml
[project]
name = "my_contract"
version = "0.1.0"
authors = ["Alice <[email removed]>"]
entry = "main.sw"          # Default: main.sw (scripts/contracts) or lib.sw (libraries)
license = "Apache-2.0"
implicit-std = true        # Whether to implicitly depend on sway-std
```

| Field | Type | Default | Description |
|---|---|---|---|
| `name` | String | required | Package name |
| `version` | String | required | SemVer package version |
| `authors` | String[] | `[]` | Author list |
| `entry` | String | `main.sw` / `lib.sw` | Entry file relative to `src/` |
| `license` | String | `""` | SPDX license identifier |
| `implicit-std` | bool | `true` | Auto-add `sway-std` dependency |

#### `[dependencies]` Section

```toml
[dependencies]
# Path dependency
my_lib = { path = "../my_lib" }

# Git dependency (tag, branch, or rev)
sway_standards = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.4.0" }

# IPFS dependency (CID-based)
my_package = { ipfs = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG" }
```

| Source Type | Fields | Notes |
|---|---|---|
| Path | `path` | Relative or absolute filesystem path |
| Git | `git`, `tag` / `branch` / `rev` | Fetched via git clone; cached in `~/.forc/` |
| IPFS | `ipfs` | CID-based; fetched from IPFS network |

#### `[patch]` Section

```toml
[patch."https://github.com/FuelLabs/sway-standards"]
sway_standards = { path = "../local-standards" }
```

Overrides remote dependencies with local versions for development. Follows the
same semantics as Cargo's `[patch]`.

#### `[build-profile]` Section

```toml
[build-profile.release]
optimization_level = "1"      # "0" = Opt0 (default), "1" = Opt1
print_dasm = false
print_finalized_asm = false
print_ir = false
```

| Field | Values | Default | Description |
|---|---|---|---|
| `optimization_level` | `"0"`, `"1"` | `"0"` | IR optimization aggressiveness |
| `print_dasm` | bool | `false` | Print desugared ASM to stdout |
| `print_finalized_asm` | bool | `false` | Print final allocated ASM |
| `print_ir` | bool | `false` | Print generated SSA IR |

#### `[workspace]` Section (Multi-package Projects)

```toml
[workspace]
members = [
    "contracts/my_contract",
    "libraries/my_lib",
    "scripts/my_script",
]
```

### 3.2 Forc.lock — Lockfile

`Forc.lock` is auto-generated and must not be edited manually. It records exact
resolved versions and content hashes for all transitive dependencies, ensuring
reproducible builds across machines and CI environments.

```toml
[[package]]
name = "core"
source = "path+from-root-..."
version = "0.0.0"

[[package]]
name = "sway_standards"
source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.4.0#abc123def"
version = "0.4.0"
dependencies = ["core", "std"]
```

Commit `Forc.lock` to version control for all non-library packages. Libraries
may omit it to avoid conflict with downstream consumers.

### 3.3 swayfmt.toml — Formatter Configuration

`swayfmt.toml` is the formatter configuration file. `swayfmt` searches from
the project directory upward to the filesystem root. If absent, all defaults
apply.

> [!IMPORTANT]
> `swayfmt.toml` is **optional**. The built-in defaults produce fully valid,
> community-standard formatting. Only add this file when your team needs to
> deviate from the defaults. Commit it to version control and enforce
> `forc fmt --check` in CI to prevent formatting drift.

#### Whitespace Section

```toml
[whitespace]
tab_spaces = 4            # Spaces per indent level
newline_style = "Auto"    # "Auto" | "Unix" | "Windows" | "Native"
indent_style = "Block"    # "Block" | "Visual"
```

| Field | Default | Options | Description |
|---|---|---|---|
| `tab_spaces` | `4` | integer | Spaces per indent |
| `newline_style` | `Auto` | `Auto`, `Unix`, `Windows`, `Native` | Line ending style |
| `indent_style` | `Block` | `Block`, `Visual` | Indentation alignment mode |

#### Imports Section

```toml
[imports]
group_imports = "StdlibFirst"    # "Preserve" | "One" | "StdlibFirst"
import_granularity = "Preserve"  # "Preserve" | "Item" | "Crate" | "Module"
```

| Field | Default | Options | Description |
|---|---|---|---|
| `group_imports` | `StdlibFirst` | `Preserve`, `One`, `StdlibFirst` | Import group ordering |
| `import_granularity` | `Preserve` | `Preserve`, `Item`, `Crate`, `Module` | Merge/split use trees |

#### Expressions Section

```toml
[expressions]
expr_brace_style = "SameLineWhere"
```

| Field | Default | Description |
|---|---|---|
| `expr_brace_style` | `SameLineWhere` | Brace and where-clause placement style |

#### Literals Section

```toml
[literals]
hex_literal_case = "Preserve"   # "Preserve" | "Upper" | "Lower"
```

#### Structures Section

```toml
[structures]
field_alignment = "Off"   # "Off" | "AlignFields"
```

| Field | Default | Description |
|---|---|---|
| `field_alignment` | `Off` | When `AlignFields`, aligns struct field type annotations |

#### Heuristics Section

Controls character-width thresholds that determine when the formatter breaks
a line vs. keeps it inline. Values are integers representing character counts.

```toml
[heuristics]
# (threshold fields — specific names are format-version dependent)
```

#### Comments Section

Controls how inline and doc comments are reflowed and positioned relative to
the code they annotate.

#### Ordering Section

Controls ordering of items within modules (e.g., whether `use` declarations
are grouped before `fn` declarations).

### 3.4 Environment Variables

| Variable | Purpose | Example |
|---|---|---|
| `FORC_EXPERIMENTAL` | Enable experimental features (comma-separated) | `FORC_EXPERIMENTAL=new_encoding,references` |
| `FORC_NO_EXPERIMENTAL` | Disable experimental features | `FORC_NO_EXPERIMENTAL=new_hashing` |
| `FORC_PUB_TOKEN` | Auth token for `forc publish` | `FORC_PUB_TOKEN=<registry-token>` |
| `FORC_IMPLICIT_STD_PATH` | Override path to `sway-std` standard library | `FORC_IMPLICIT_STD_PATH=/path/to/sway-std` |
| `FORC_IMPLICIT_STD_GIT` | Override git URL for implicit std | `FORC_IMPLICIT_STD_GIT=https://github.com/...` |
| `FORC_IMPLICIT_STD_GIT_TAG` | Pin std to specific git tag | `FORC_IMPLICIT_STD_GIT_TAG=v0.71.0` |
| `FORC_IMPLICIT_STD_GIT_BRANCH` | Pin std to specific branch | `FORC_IMPLICIT_STD_GIT_BRANCH=master` |
| `CARGO_MANIFEST_DIR` | Test harness: locates test assets | Set automatically by Cargo during `cargo test` |
| `RUST_BACKTRACE` | Enable Rust backtraces for ICE debugging | `RUST_BACKTRACE=full` |

### 3.5 Experimental Feature Flags

Managed by the `sway-features` crate. Features are toggled via environment
variables (future: `Forc.toml` support planned).

| Feature | Flag Name | Description |
|---|---|---|
| New encoding | `new_encoding` | Revised ABI encoding scheme |
| References | `references` | Reference types (`&T`, `&mut T`) in Sway |
| New hashing | `new_hashing` | Updated hash primitive semantics |
| Str array no padding | `str_array_no_padding` | Removes padding from string array encoding |
| Dynamic storage | `dynamic_storage` | Dynamic storage key computation at runtime |

```bash
# Enable multiple features
FORC_EXPERIMENTAL=new_encoding,references forc build

# Disable a feature that would otherwise be on
FORC_NO_EXPERIMENTAL=dynamic_storage forc build
```

> [!IMPORTANT]
> Experimental features may introduce breaking changes between minor versions.
> Never enable experimental features in production contracts without thorough
> testing. The `new_encoding` feature changes the ABI wire format — enabling it
> on an already-deployed contract is a breaking change for all callers.

---

## 4. Deployment & Scaling

### 4.1 Building the Toolchain from Source

```bash
# Clone the repository
git clone https://github.com/FuelLabs/sway.git
cd sway

# Install Rust toolchain (respects rust-toolchain.toml)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"

# Build all workspace members (debug)
cargo build --workspace

# Build release binaries
cargo build --release --workspace

# Install forc and all plugins to ~/.cargo/bin
cargo install --path forc
cargo install --path forc-plugins/forc-fmt
cargo install --path forc-plugins/forc-lsp
cargo install --path forc-plugins/forc-debug
cargo install --path forc-plugins/forc-doc
cargo install --path forc-plugins/forc-migrate
cargo install --path forc-plugins/forc-publish
cargo install --path forc-plugins/forc-tx
```

### 4.2 Installing via fuelup (Recommended for End Users)

`fuelup` is the Fuel toolchain manager (analogous to `rustup`). It manages
multiple `forc` versions and the associated `fuel-core` node binary.

```bash
# Install fuelup
curl https://install.fuel.network | sh

# Install the latest stable Fuel toolchain
fuelup toolchain install latest
fuelup default latest

# List installed toolchains
fuelup toolchain list

# Install a specific version
fuelup toolchain install nightly
fuelup toolchain install v0.71.0

# Verify installation
forc --version
fuel-core --version
```

### 4.3 CI/CD Pipeline Integration

#### Full Toolchain CI (Contributing to Sway)

```yaml
name: Sway Toolchain CI

on: [push, pull_request]

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Rust (pinned via rust-toolchain.toml)
        uses: dtolnay/rust-toolchain@stable

      - name: Install just
        uses: extractions/setup-just@v1

      - name: Cache cargo registry
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

      - name: Check sorted dependencies
        run: cargo install cargo-sort && cargo sort --check --workspace

      - name: Lint
        run: cargo clippy --all-targets --workspace -- -D warnings

      - name: Format check
        run: cargo fmt --check --all

      - name: Build
        run: cargo build --release --workspace

      - name: Test
        run: cargo test --workspace
```

#### Sway Project CI (For Contract Developers)

```yaml
name: Contract CI

on: [push, pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install fuelup
        run: curl https://install.fuel.network | sh

      - name: Install Fuel toolchain
        run: |
          fuelup toolchain install latest
          fuelup default latest

      - name: Format check
        run: forc fmt --check

      - name: Build (locked — no dependency updates)
        run: forc build --locked

      - name: Run tests
        run: forc test --locked
```

### 4.4 Package Dependency Cache

`forc-pkg` caches downloaded packages under `~/.forc/`:

```
~/.forc/
  cache/
    git/
      <repo-hash>/          # Bare git clones of dependencies
        HEAD
        config
        objects/
    ipfs/
      <cid>/                # IPFS-fetched package contents
```

Cache invalidation is keyed by content hash, so stale entries are never silently
used. In containerized CI, mount `~/.forc/cache` as a named volume or use the
CI platform's cache action to persist across runs.

> [!NOTE]
> Cache entries are never automatically pruned. In long-running CI systems,
> periodically clear `~/.forc/cache/git/` if disk space becomes a concern.
> The next build will re-fetch and re-validate all dependencies.

### 4.5 Cross-Compilation (Compiler Binary)

The Sway compiler is a Rust program and cross-compiles using standard Rust
tooling. The generated Sway bytecode always targets FuelVM or EVM regardless
of the host architecture.

```bash
# Build forc for Linux ARM64 on Linux x86_64
rustup target add aarch64-unknown-linux-gnu
cargo build --release --target aarch64-unknown-linux-gnu -p forc
```

### 4.6 Workspace Builds (Multi-package Projects)

```bash
# Build all workspace members
forc build --path /workspace/root

# Check all members without codegen (fast)
forc check --path /workspace/root

# Build and test a specific member
forc build --path /workspace/root/contracts/token
forc test --path /workspace/root/contracts/token

# Locked offline build for reproducibility
forc build --path /workspace/root --locked --offline
```

### 4.7 Output Artifacts

`forc build` produces output in the `out/` directory by default:

```
out/
  debug/                    # or release/ when --release is used
    <name>.bin              # FuelVM bytecode
    <name>-abi.json         # JSON ABI
    <name>-storage_slots.json  # Storage slot initializers
```

Override output directory:

```bash
forc build --output-dir ./artifacts/
forc build --output-bin-path ./artifacts/my_contract.bin
```

---

## 5. Operations

### 5.1 forc CLI Subcommands

The `forc` CLI (`forc/src/main.rs` → `forc/src/cli/mod.rs`) dispatches to
16 built-in subcommands plus any discovered `forc-*` plugins.

> [!NOTE]
> Run `forc help <subcommand>` or `forc <subcommand> --help` for complete
> argument documentation. All subcommands accept `--path <dir>` to specify the
> project root (defaults to current working directory).

| Subcommand | Purpose |
|---|---|
| `forc new` | Scaffold a new Sway project |
| `forc init` | Initialize Sway project in existing directory |
| `forc build` | Compile Sway project to bytecode + ABI |
| `forc check` | Type-check without codegen |
| `forc clean` | Remove build artifacts (`out/` directory) |
| `forc deploy` | Deploy contract to a Fuel network |
| `forc run` | Run a script against a Fuel node |
| `forc test` | Run in-language unit tests |
| `forc update` | Update dependencies in `Forc.lock` |
| `forc add` | Add a dependency to `Forc.toml` |
| `forc remove` | Remove a dependency from `Forc.toml` |
| `forc contract-id` | Compute deterministic contract ID |
| `forc parse-bytecode` | Disassemble and display compiled bytecode |
| `forc completions` | Generate shell completion scripts |
| `forc plugins` | List all discovered `forc-*` plugins |
| `forc addr2line` | Resolve bytecode addresses to source locations |

### 5.2 forc build — Complete Flag Reference

```
forc build [OPTIONS]

Core Options:
  --path <PATH>                    Project root [default: .]
  --release                        Enable Opt1 IR optimizations
  --profile <PROFILE>              Use named build profile from Forc.toml
  --target <TARGET>                Build target: fuel (default) or evm
  --locked                         Require Forc.lock to be current; fail if not
  --offline                        No network access; use cache only
  --ipfs-node <URL>                Custom IPFS gateway URL

Output Options:
  --output-dir <DIR>               Override output directory [default: out/]
  --output-bin-path <PATH>         Override output .bin path
  --json-abi                       Emit ABI as JSON to stdout
  --json-abi-with-callpaths        Emit ABI with fully-qualified call paths

Diagnostic Options:
  --print-ast                      Print typed AST to stdout
  --print-dasm                     Print desugared ASM
  --print-finalized-asm            Print final allocated ASM
  --print-ir                       Print generated SSA IR
  --time-phases                    Print wall-clock timing per compiler phase
  --ir-opt <PASSES>                Comma-separated IR optimization pass list
  --error-on-warnings              Treat all warnings as errors

Verbosity Options:
  -v, --verbose                    Verbose output
  -s, --silent                     Suppress all output
  --terse                          Suppress warnings in output
```

### 5.3 forc test — Complete Flag Reference

```
forc test [OPTIONS] [TEST_FILTER]

Options:
  --path <PATH>           Project root
  --release               Optimize before testing (Opt1)
  --logs                  Display VM execution logs during tests
  --raw-log               Display raw log bytes
  --filter-exact          Match test names exactly (substring match by default)
  --count                 Print test count without running
  --node-url <URL>        Fuel node URL for integration tests
  --default-salt          Use deterministic salt for reproducible contract IDs
  --locked                Require lockfile to be current
  --offline               No network; cache only
```

### 5.4 forc-debug — DAP Server

`forc-debug` implements the Debug Adapter Protocol (DAP), enabling IDE-integrated
debugging of Sway contracts and scripts running against a live Fuel node.

```bash
# Start DAP server connecting to fuel-core at default address
forc debug --serve

# Connect to a remote or non-default node
forc debug --serve --api-url http://192.168.1.100:4000/graphql
```

| Option | Default | Description |
|---|---|---|
| `--api-url` | `http://127.0.0.1:4000/graphql` | Fuel node GraphQL endpoint |
| `--serve` | off | Start DAP server on stdin/stdout |

The DAP server translates between the DAP protocol (VS Code, Neovim DAP, etc.)
and the Fuel node's debug API, supporting:
- Breakpoints (by source line and bytecode offset)
- Step over / step into / step out
- Register and memory inspection
- Stack frame navigation
- Variable watches

### 5.5 forc-lsp — Language Server

```bash
# Start LSP server (editor launches this via stdin/stdout)
forc lsp

# Verbose LSP logging (useful for LSP client debugging)
forc lsp --verbose
```

LSP capabilities implemented in `sway-lsp`:

| Capability | Supported |
|---|---|
| Text document sync | Full (on save) |
| Publish diagnostics | Yes (errors + warnings) |
| Hover (type info, doc comments) | Yes |
| Go-to-definition | Yes |
| Find all references | Yes |
| Completion (items, keywords) | Yes |
| Code actions | Yes |
| Rename symbol | Yes |
| Semantic tokens | Yes |
| Document symbols | Yes |
| Workspace symbols | Yes |
| Signature help | Yes |
| Formatting (`forc fmt` integration) | Yes |

### 5.6 forc-doc — Documentation Generation

```bash
# Generate HTML docs for current package
forc doc

# Open in default browser after generation
forc doc --open

# Generate docs for all workspace members
forc doc --workspace

# Specify output directory
forc doc --out-dir ./docs/
```

Output is placed in `out/doc/` relative to the project root. HTML is generated
using the `horrorshow` templating library following `swaydoc` conventions
(styled similar to rustdoc).

### 5.7 forc-publish — Package Registry

```bash
# Publish current package
FORC_PUB_TOKEN=<token> forc publish

# Dry run — validate without actually publishing
forc publish --dry-run

# Specify registry URL
forc publish --registry https://registry.fuel.network

# Verify your token is set
echo $FORC_PUB_TOKEN
```

> [!IMPORTANT]
> `FORC_PUB_TOKEN` must be set in the environment. Never hard-code registry
> tokens in `Forc.toml` or commit them to version control. Store them in CI
> secrets (GitHub Actions: `Settings → Secrets and variables → Actions`).

### 5.8 forc-migrate — Breaking Change Migration

`forc-migrate` automates source-level migrations when Sway introduces breaking
language changes. The plugin contains 10 migration definitions (~51K chars).

```bash
# List available migrations and which apply to current code
forc migrate list

# Apply all applicable migrations to current project
forc migrate

# Preview changes without modifying files
forc migrate --dry-run

# Apply a specific migration
forc migrate <migration-name>
```

> [!NOTE]
> Always run `forc migrate --dry-run` and review the diff before applying.
> Commit the un-migrated code first so the migration is a separate, reviewable
> commit.

### 5.9 forc-fmt — Code Formatter

```bash
# Format all .sw files in project
forc fmt

# Check formatting in CI (exit code 1 if any file needs changes)
forc fmt --check

# Format a specific file
forc fmt --path src/main.sw

# Use a specific config file
forc fmt --config-path /path/to/swayfmt.toml
```

The formatter is deterministic and idempotent: running it twice on any file
produces identical output. All contributions to the Sway repository must pass
`forc fmt --check` in CI.

### 5.10 forc-tx — Transaction Builder

```bash
# Build a transaction (subcommands vary by tx type)
forc tx create [OPTIONS]
forc tx script [OPTIONS]
```

`forc-tx` is used for constructing raw Fuel transactions programmatically,
particularly useful for testing contract interactions outside of the SDK.

### 5.11 Operational Runbooks

#### Diagnosing a Compilation Failure

```bash
# Step 1: Full verbose output
RUST_BACKTRACE=1 forc build --verbose 2>&1 | tee build.log

# Step 2: Check which phase failed
forc build --time-phases 2>&1 | tail -20

# Step 3: Inspect IR for type/codegen issues
forc build --print-ir 2>&1 | tee ir_dump.txt

# Step 4: Inspect typed AST for type checker issues
forc build --print-ast 2>&1 | tee ast_dump.txt

# Step 5: Inspect final ASM for code generation issues
forc build --print-finalized-asm 2>&1 | tee asm_dump.txt
```

> [!WARNING]
> If the compiler panics (ICE — Internal Compiler Error), this is always a bug
> in the compiler, not your code. File an issue at
> https://github.com/FuelLabs/sway/issues with the full panic message,
> `RUST_BACKTRACE=full` output, and the smallest possible reproducer.

#### Resolving Dependency Conflicts

```bash
# Update all dependencies to latest compatible versions
forc update

# Update a specific dependency
forc update sway_standards

# View the full dependency tree
# (if forc-tree plugin is installed)
forc tree

# Force re-resolve (delete lockfile and rebuild)
rm Forc.lock && forc build
```

> [!WARNING]
> Deleting `Forc.lock` in a production project may pull in newer transitive
> dependency versions that introduce breaking changes. Prefer `forc update
> <specific-dep>` for surgical dependency updates.

#### Clearing the Package Cache

```bash
# Clear all cached packages (will re-fetch on next build)
rm -rf ~/.forc/cache/

# Clear only git dependency caches
rm -rf ~/.forc/cache/git/

# Clear only IPFS caches
rm -rf ~/.forc/cache/ipfs/
```

#### Verifying a Build is Reproducible

```bash
# Build 1
forc build --locked --offline
sha256sum out/debug/my_contract.bin > hash1.txt

# Clean and rebuild
forc clean
forc build --locked --offline
sha256sum out/debug/my_contract.bin > hash2.txt

# Compare (should be identical)
diff hash1.txt hash2.txt
```

---

## 6. Performance

### 6.1 Compiler Performance Characteristics

The Sway compiler is designed for incremental workloads in LSP contexts.
`sway-lsp` maintains a persistent in-memory typed program state, recompiling
only on file save. For batch `forc build`, performance scales approximately
linearly with total source size.

> [!NOTE]
> The LSP uses `dashmap` (lock-free concurrent HashMap) throughout `sway-lsp`
> to allow parallel read-heavy IDE operations (hover, completion, references)
> while serializing write-heavy compilation updates. This provides sub-10ms
> response times for most IDE interactions on typical contract codebases.

### 6.2 Optimization Levels

| Level | `forc build` flag | `Forc.toml` value | Description |
|---|---|---|---|
| Opt0 | (default) | `optimization_level = "0"` | No IR optimization; fastest compile time |
| Opt1 | `--release` | `optimization_level = "1"` | Full IR optimization suite |

Use Opt0 during development for fast iteration. Opt1 for production: the
resulting bytecode is meaningfully smaller (fewer instructions) and faster
(fewer redundant computations on-chain, lowering gas costs).

### 6.3 IR Optimization Passes

The `sway-ir` pass manager applies passes in a configured sequence. Individual
passes can be selected with `--ir-opt <pass1,pass2,...>`.

| Pass | Kebab Name | Description |
|---|---|---|
| Constant folding | `const-folding` | Evaluate pure constant expressions at compile time |
| Constant demotion | `const-demotion` | Spill large constants from registers to memory |
| Function inlining | `fn-inline` | Inline small or single-call functions |
| Dead code elimination | `dce` | Remove unreachable code and unused values |
| Scalar replacement of aggregates | `sroa` | Decompose struct accesses into scalar operations |
| Simplify CFG | `simplify-cfg` | Merge basic blocks, remove unreachable blocks |
| Memory to register | `mem2reg` | Promote stack allocations to SSA registers |
| Loop invariant code motion | `licm` | Hoist loop-invariant computations out of loops |

Custom pass sequence example:

```bash
forc build --release --ir-opt "const-folding,fn-inline,dce,simplify-cfg,mem2reg"
```

### 6.4 Performance Benchmarking with just

```bash
# End-to-end compilation performance benchmark
just perf-e2e

# In-language test execution performance
just perf-in-lang

# Run all benchmarks
just perf-all

# Diff current performance against the previous baseline
just perf-diff

# Diff against the latest published release
just perf-diff-latest
```

Performance data is collected with the `--perf` flag on the test harness,
measuring wall-clock time per compiler phase.

### 6.5 Memory Allocator

`tikv-jemallocator` is configured as the global Rust allocator for `forc` and
other binaries. jemalloc outperforms the system allocator for compiler workload
patterns (high rates of small, short-lived allocations during parsing and type
checking).

```rust
// Applied in forc/src/main.rs
#[cfg(feature = "jemalloc")]
#[global_allocator]
static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
```

### 6.6 Build Caching with sccache

For large CI environments building the Sway compiler itself frequently:

```bash
# Install sccache
cargo install sccache

# Set sccache as the Rust compiler wrapper
export RUSTC_WRAPPER=sccache

# Build with caching
cargo build --release --workspace

# View cache statistics
sccache --show-stats
```

### 6.7 Parallel Package Builds

`forc-pkg` constructs a dependency DAG using `petgraph` and builds packages in
topological order. Independent packages are built in parallel (thread count
defaults to number of logical CPUs, configurable with `--jobs`/`-j`):

```bash
# Use 8 parallel jobs
forc build --jobs 8

# Use half the available CPUs
forc build --jobs $(nproc --ignore=1)
```

---

## 7. Security

### 7.1 Open Security Advisories

> [!CAUTION]
> Two active RUSTSEC advisories affect the Sway toolchain dependency tree as
> of source commit **e12e611** (version 0.71.0). Review these before deploying
> build infrastructure that processes untrusted Sway source code.

#### RUSTSEC-2025-0055 — ANSI Escape Sequence Log Poisoning (Issue #7589)

**Affected:** A logging/terminal display dependency in the toolchain.

**Risk:** Maliciously crafted content — such as a package name or compiler
error message containing ANSI escape sequences — could manipulate terminal
output. In CI systems displaying raw build logs, this could suppress or hide
critical warnings from human reviewers.

**Mitigation:**

```bash
# Strip ANSI codes from forc output in automated pipelines
forc build 2>&1 | sed 's/\x1B\[[0-9;]*[mK]//g' > build.log

# Or use --terse to reduce styled output
forc build --terse 2>&1 > build.log
```

- Pin the affected transitive dependency to a patched version once available.
- Use `--json-abi` for programmatic ABI consumption instead of parsing terminal
  output.

#### RUSTSEC-2026-0049 — CRL Matching Logic Flaw (Issue #7576)

**Affected:** TLS certificate validation in the HTTPS dependency-fetching path.

**Risk:** Certificate Revocation Lists (CRLs) may not be properly honored
during git or IPFS dependency fetching. A revoked TLS certificate for a
dependency host could be accepted, enabling potential man-in-the-middle attacks
on dependency downloads.

**Mitigation:**

```bash
# Use --locked --offline for all production/CI builds
# This prevents dependency fetching entirely
forc build --locked --offline
```

- Fetch dependencies on a separate, network-isolated build step; then pass
  `--offline` to the actual compilation step.
- Apply the patched dependency version once the upstream fix is merged and
  released.

> [!WARNING]
> Never run `forc build` against untrusted `Forc.toml` files without sandboxing.
> A malicious `Forc.toml` could cause `forc-pkg` to fetch and compile arbitrary
> Sway source from remote git repositories. Use `--locked --offline` to prevent
> this, or run in an isolated container with `--network none`.

### 7.2 Supply Chain Security

#### Dependency Pinning

```bash
# Audit all Rust dependencies for known advisories
cargo install cargo-audit
cargo audit

# Generate a Software Bill of Materials
cargo install cargo-sbom
cargo sbom > sbom.json

# Ensure Forc.lock is committed and unchanged
git diff --exit-code Forc.lock || (echo "Forc.lock has uncommitted changes" && exit 1)
```

#### Reproducible Builds

```bash
# Always use --locked in CI to prevent accidental dependency updates
forc build --locked

# Verify output bytecode hash against a known-good value
EXPECTED="sha256:abc123..."
ACTUAL=$(sha256sum out/debug/my_contract.bin | awk '{print "sha256:"$1}')
[ "$EXPECTED" = "$ACTUAL" ] || (echo "Bytecode mismatch!" && exit 1)
```

### 7.3 Sandboxing Untrusted Builds

When compiling untrusted Sway source (e.g., third-party contract submissions
or security research):

```bash
# Minimal Docker sandbox
docker run --rm \
  --network none \
  --read-only \
  --tmpfs /tmp:exec,size=512m \
  -v /path/to/project:/workspace:ro \
  -v /path/to/output:/out:rw \
  ghcr.io/fuellabs/fuel-toolchain:latest \
  forc build \
    --path /workspace \
    --output-dir /out \
    --locked \
    --offline

# Even more restricted: drop all capabilities
docker run --rm \
  --network none \
  --read-only \
  --tmpfs /tmp:exec,size=512m \
  --cap-drop ALL \
  --security-opt no-new-privileges \
  -v /path/to/project:/workspace:ro \
  -v /path/to/output:/out:rw \
  ghcr.io/fuellabs/fuel-toolchain:latest \
  forc build --path /workspace --output-dir /out --locked --offline
```

Key isolation measures:
- `--network none` — Prevents `forc-pkg` from fetching remote dependencies
- `--read-only` — Source is read-only; builds go to a writable volume
- `--locked --offline` — Enforces pre-resolved lockfile; no network access
- `--cap-drop ALL` — No Linux capabilities (prevents privilege escalation)

### 7.4 CEI Pattern Analysis — Reentrancy Detection

The Sway compiler performs **Checks-Effects-Interactions (CEI)** pattern
analysis to detect reentrancy vulnerability patterns at compile time. A CEI
violation occurs when a storage write ("effect") is performed after an external
contract call ("interaction").

```sway
contract;

abi VulnerableContract {
    fn withdraw(amount: u64);
}

impl VulnerableContract for Contract {
    fn withdraw(amount: u64) {
        let sender = msg_sender().unwrap();
        
        // INTERACTION: external call before state update
        transfer(amount, AssetId::base(), sender);
        
        // EFFECT: storage update after — CEI violation warning
        storage.balance.write(storage.balance.read() - amount);
    }
}
```

Correct CEI pattern:

```sway
fn withdraw(amount: u64) {
    let sender = msg_sender().unwrap();
    
    // EFFECT first: update state
    storage.balance.write(storage.balance.read() - amount);
    
    // INTERACTION after: now safe
    transfer(amount, AssetId::base(), sender);
}
```

> [!WARNING]
> CEI warnings are currently **nondeterministic** (GitHub issue #7606). The
> same source file may or may not trigger the warning across different
> compilations. Do not rely solely on the CEI checker. Apply manual code
> review, test reentrancy scenarios explicitly, and treat any CEI warning as
> a definitive finding requiring immediate remediation.

To treat CEI violations as hard errors:

```bash
forc build --error-on-warnings
```

### 7.5 Compiler Security Properties

| Property | Implementation |
|---|---|
| No arbitrary OS syscalls | FuelVM is a sandboxed virtual machine; no OS access |
| Memory safety (compiler) | Rust ownership system throughout the compiler |
| Memory safety (contracts) | FuelVM has no raw pointer arithmetic |
| Integer overflow | Sway panics on overflow in debug; configurable in release |
| Reentrancy detection | CEI pattern analysis at compile time (with caveats) |
| Immutable storage keys | Storage key layout computed deterministically from ABI |
| Deterministic contract IDs | Contract ID = hash of bytecode + salt; fully deterministic |

### 7.6 ABI Encoding Security

The generated ABI JSON specifies the canonical encoding for all public
contract functions. Incorrect encoding causes transaction revert (not silent
data corruption). Key points:

- Function selectors are 4-byte SHA-256 prefixes of the canonical signature
- Parameter encoding is strict; mismatches revert
- The `new_encoding` experimental feature **changes the wire format** — enabling
  it on an already-deployed contract breaks all callers using the old format
- Configurable constants (`configurables`) are embedded in bytecode at deploy
  time and cannot be changed post-deployment

---

## 8. Developer Internals

### 8.1 Compiler Pipeline — Phase-by-Phase Analysis

#### Phase 1: Parsing (`sway-parse`)

**Source size:** 17 files, 121K characters

The parser is a hand-written recursive-descent parser operating in two stages:

**Lexer** tokenizes source text into a typed token stream:
- Keywords (`fn`, `let`, `match`, `if`, `contract`, ...)
- Identifiers, integer literals, string literals, boolean literals
- Operators, punctuation, delimiters
- Doc comments (`///`) preserved as AST nodes
- Full byte-offset span tracking per token

**Parser** consumes tokens and produces `sway-ast` node trees:
- Uses `ParseToEnd` and `ParseBracket` combinators for delimiter-bounded sequences
- Recursive descent with direct precedence climbing for expressions
- Error recovery is minimal; most parse errors are immediately fatal
- All produced nodes carry `Span` information for downstream error reporting

Key public entry point:

```rust
pub fn parse_file(
    handler: &Handler,
    src: Arc<str>,
    path: Option<Arc<PathBuf>>,
) -> Result<ParsedTree, ErrorEmitted>
```

#### Phase 2: AST Representation (`sway-ast`)

`sway-ast` defines the **concrete syntax tree** — a direct structural reflection
of the source text. All nodes carry `Span`. The AST is NOT yet type-annotated
at this stage.

Key node families:

| Family | Node Examples |
|---|---|
| Items (top-level declarations) | `ItemFn`, `ItemImpl`, `ItemTrait`, `ItemStruct`, `ItemEnum`, `ItemStorage`, `ItemConst`, `ItemUse`, `ItemConfigurable` |
| Expressions | `ExprIf`, `ExprMatch`, `ExprBlock`, `ExprCall`, `ExprMethodCall`, `ExprBinary`, `ExprUnary`, `ExprIndex`, `ExprTuple` |
| Type expressions | `TyTuple`, `TyArray`, `TyPath`, `TyInfer`, `TyStr`, `TyPrimitive`, `TyPtr`, `TySlice` |
| Patterns | `PatLiteral`, `PatIdent`, `PatTuple`, `PatStruct`, `PatEnum`, `PatWildcard`, `PatOr` |
| Statements | `StatementLet`, `StatementExpr` |

#### Phase 3: Type Checking (`sway-core` — `type_system/`)

**Source size:** 282K characters — the largest single subsystem

The type checker performs six major operations:

1. **Name resolution** — Resolves identifiers to declarations in the namespace,
   traversing module boundaries and handling `use` imports.

2. **Type inference** — Bidirectional type inference with constraint propagation.
   Types flow both top-down (from context) and bottom-up (from literals and calls).

3. **Monomorphization** — Instantiates generic functions and types with concrete
   type arguments. Memoized in the declaration engine to avoid duplicate work.

4. **Trait resolution** — Resolves which `impl Trait for T` block satisfies each
   trait constraint, checking that all associated types and methods are provided.

5. **Type unification** — Merges type variables with concrete types during
   inference. Failed unification produces type mismatch errors.

6. **Coercion** — Applies implicit coercions where permitted (e.g., `b256` to
   `Address`).

The type system uses **TypeId** handles (integer indices) into the `TypeEngine`
to represent all types, avoiding recursive data structures:

```rust
// The TypeEngine maps TypeId -> TypeInfo
pub enum TypeInfo {
    Unknown,
    UnknownGeneric { name: Ident, trait_constraints: VecSet<TraitConstraint> },
    Placeholder(TypeParameter),
    TypeParam(usize),
    StringSlice,
    StringArray { length: Length },
    UnsignedInteger(IntegerBits),  // U8, U16, U32, U64, U256
    Boolean,
    Tuple(Vec<TypeArgument>),
    B256,
    Numeric,               // Unresolved numeric literal
    Contract,
    ErrorRecovery(ErrorEmitted),
    Array(TypeArgument, Length),
    RawUntypedPtr,
    RawUntypedSlice,
    Ptr(TypeArgument),
    Slice(TypeArgument),
    Enum(DeclRefEnum),
    Struct(DeclRefStruct),
    ContractCaller { abi_name: AbiName, address: Box<TypedExpression> },
    Custom { qualified_call_path: QualifiedCallPath, type_arguments: Option<Vec<TypeArgument>> },
    SelfType,
    Alias { name: Ident, ty: TypeArgument },
    TraitType { name: Ident, trait_type_id: TraitTypeId },
}
```

**Known active issues:**
- **#7603** — ICE from invalid type unification of arrays (type variable scope escape)
- **#7604** — Compiler panic with type aliases + const generic arrays
- **#7602** — ICE when indexing `self[i]` with const generic index
- **#7605** — Confusing out-of-bounds error for const generic arrays

#### Phase 4: Declaration Engine (`sway-core` — `decl_engine/`)

**Source size:** 93K characters

The declaration engine manages the lifecycle of all named declarations using
opaque integer handles, decoupling declaration identity from type-checking state.
This enables incremental recompilation: unchanged declarations retain their
handles and cached type information across rebuilds.

Core types:

```rust
pub struct DeclEngine {
    // Stores all typed declarations by DeclId
    // Supports: function, struct, enum, trait, impl, ...
}

// Typed handle to a specific declaration
pub struct DeclRef<T> {
    pub name: Ident,
    pub id: DeclId,
    pub decl_span: Span,
    _marker: PhantomData<T>,
}

pub struct DeclId(usize);  // Opaque integer
```

The declaration engine also caches monomorphized instances, so
`Vec<u64>` and `Vec<bool>` are each generated once regardless of how
many times they appear in the codebase.

#### Phase 5: Control Flow Analysis

Two analysis passes run on the fully typed AST:

**Dead Code Analysis**
- Constructs a reachability graph from all entry points
- Marks unused functions, variables, struct fields, and `use` imports
- Emits `Warning::DeadCode` variants for each unused item
- Respects visibility: `pub` items are considered reachable even if not locally called

**CEI Pattern Analysis**
- Scans each function body for the pattern: external contract call followed by storage write
- Constructs a partial temporal order of side-effecting operations
- Emits `Warning::StorageWriteAfterContractCall` on violations
- **Known issue #7606**: HashMap iteration order affects which violations are detected
  in which order; the set of reported violations can vary between invocations

#### Phase 6: IR Generation (`sway-ir`)

**Source size:** 481K characters, 21 files

The compiler lowers the typed AST to SSA-form (Static Single Assignment)
intermediate representation. Every variable is assigned exactly once; phi
nodes merge values at control flow join points.

IR container hierarchy:

```
Module
  └── Function (one per Sway function)
        ├── Argument list
        └── Block (basic block: sequential instructions, ends with branch/ret)
              └── Instruction (SSA value-producing or effect-producing)
```

All IR instruction variants:

| Instruction | Description |
|---|---|
| `AsmBlock` | Inline assembly block (raw FuelASM) |
| `BitCast` | Bitwise reinterpretation between types of equal size |
| `BinaryOp` | Arithmetic (+, -, *, /, %) and bitwise (&, |, ^, <<, >>) |
| `Branch` | Unconditional jump to a basic block |
| `Call` | Internal function call |
| `CastPtr` | Pointer type cast (changes pointee type, not bits) |
| `Cmp` | Comparison: eq, ne, lt, le, gt, ge |
| `ConditionalBranch` | Conditional jump: `if cond goto true_bb else false_bb` |
| `ContractCall` | External contract invocation via ABI |
| `ExtractElement` | Extract element from array or slice |
| `ExtractValue` | Extract field from struct/tuple by index path |
| `FuelVm(FuelVmInstruction)` | FuelVM-specific: `Log`, `Revert`, `Smo`, `StateClear`, `StateLoadQuadWord`, `StateLoadWord`, `StateStoreQuadWord`, `StateStoreWord`, `WideUnaryOp`, `WideBinaryOp`, `WideCmpOp`, `WideModularOp` |
| `GetElemPtr` | GEP-style: compute pointer to sub-element of aggregate |
| `GetLocal` | Get pointer to a local (stack) variable |
| `GetGlobal` | Get pointer to a module-level global |
| `InsertElement` | Insert element into array/slice (returns new value) |
| `InsertValue` | Insert field into struct/tuple (returns new value) |
| `IntToPtr` | Cast integer to raw pointer |
| `Load` | Dereference pointer |
| `MemCopyBytes` | Copy N bytes between two pointers |
| `MemCopyVal` | Typed copy between two pointers |
| `Nop` | No-operation (placeholder) |
| `PtrToInt` | Cast pointer to integer |
| `Ret` | Return from function |
| `Revert` | Revert the transaction with a code |
| `Store` | Write value through pointer |

IR text format for debugging:

```
// Example IR snippet (schematic)
fn my_function(a: u64, b: u64) -> u64 {
entry(a: u64, b: u64):
  v0 = add a, b
  ret u64 v0
}
```

```bash
# Dump IR to stdout during build
forc build --print-ir

# Parse IR text back to IR data structure (for testing)
# (internal tool; no direct forc command)
```

#### Phase 7: IR Optimization

The `PassManager` orchestrates optimization passes. Each pass implements:

```rust
pub trait Pass {
    fn name(&self) -> &str;
    fn descr(&self) -> &str;
    fn run(
        &self,
        module: &mut Module,
        analysis_results: &AnalysisResults,
    ) -> Result<bool, IrError>;   // bool = whether the IR was modified
    fn analyses_required(&self) -> Vec<AnalysisName>;
}
```

The pass manager tracks which analyses are valid after each pass and
re-runs invalidated analyses before dependent passes execute. The default
Opt1 pass sequence is configured internally in `sway-core`.

#### Phase 8: ASM Generation (`sway-core` — `asm_generation/`)

**Source size:** 196K characters

Three-stage lowering from IR to bytecode:

**Stage 1 — Virtual ASM**
- Architecture-agnostic assembly
- Unlimited virtual registers (VRs)
- IR instructions mapped to FuelASM instruction sequences
- Memory layout computed for all locals and aggregates

**Stage 2 — Allocated ASM**
- Virtual registers mapped to physical FuelVM registers (r0–r63) via linear scan
- Spill code inserted for registers that exceed the physical count
- Calling convention enforced (argument passing, return values)

**Stage 3 — Final ASM**
- Labels resolved to byte offsets
- Jump targets patched
- Inline assembly blocks integrated
- Final instruction stream ready for bytecode emission

#### Phase 9: ABI Generation

**Fuel ABI generator** (`fuel_abi.rs`): produces the standard Fuel JSON ABI
format, including:
- All public contract functions with canonical type encoding
- Function selector (4-byte SHA-256 prefix of canonical signature)
- Storage read/write attributes
- `payable` attribute
- Log types
- Configurable constants

**EVM ABI generator** (`evm_abi.rs`): produces EVM-compatible Solidity ABI
JSON for contracts targeting the EVM build target.

### 8.2 The Engines Architecture

`sway-core` uses a central `Engines` struct to thread shared mutable state
through the compiler without passing arguments everywhere:

```rust
pub struct Engines {
    pub type_engine: TypeEngine,
    pub decl_engine: DeclEngine,
    pub parsed_decl_engine: ParsedDeclEngine,
    pub query_engine: QueryEngine,
    pub source_engine: SourceEngine,
}

impl Engines {
    pub fn te(&self) -> &TypeEngine { &self.type_engine }
    pub fn de(&self) -> &DeclEngine { &self.decl_engine }
    pub fn se(&self) -> &SourceEngine { &self.source_engine }
}
```

This pattern:
- Makes engine access explicit and auditable (not global state)
- Enables testing with isolated engine instances
- Allows the query engine to track dependencies between engine accesses
  for incremental compilation invalidation

### 8.3 Module Reference — All Workspace Crates

#### `sway-parse`

| Component | Location | Description |
|---|---|---|
| Lexer | `src/lexer/` | Tokenizes source text; produces `TokenStream` |
| Parser entry | `src/lib.rs` | `parse_file()` public API |
| Expression parser | `src/expr/` | All expression parsing rules |
| Item parser | `src/item/` | Top-level declaration parsing |
| Type parser | `src/ty/` | Type expression parsing |
| Pattern parser | `src/pattern/` | Pattern matching construct parsing |
| Combinators | `src/priv_prelude.rs` | `ParseToEnd`, `ParseBracket`, `Peek` |

#### `sway-ast`

| Component | Location | Description |
|---|---|---|
| Expressions | `src/expr/` | All expression AST variants |
| Items | `src/item/` | All declaration AST variants |
| Types | `src/ty.rs` | Type expression variants |
| Patterns | `src/pattern.rs` | Pattern variants |
| Literals | `src/literal.rs` | Literal value types |

#### `sway-core`

| Sub-module | Approx Size | Description |
|---|---|---|
| `type_system/` | 282K chars | Type inference, unification, monomorphization, trait resolution |
| `decl_engine/` | 93K chars | Declaration lifecycle, handle-based storage |
| `asm_generation/` | 196K chars | Virtual → Allocated → Final assembly |
| `ir_generation/` | significant | Typed AST → `sway-ir` lowering |
| `control_flow_analysis/` | moderate | Dead code, CEI analysis |
| `language/` | significant | Typed AST node definitions (parallel to `sway-ast`) |
| `semantic_analysis/` | significant | Name resolution, namespace management |
| `transform/` | moderate | AST desugaring and normalization passes |
| `query_engine/` | moderate | Query-based incremental compilation interface |

#### `sway-ir`

| Component | File | Description |
|---|---|---|
| Module | `src/module.rs` | Top-level IR container |
| Function | `src/function.rs` | IR function (args, return type, blocks) |
| Basic Block | `src/block.rs` | Sequence of instructions + terminator |
| Instruction | `src/instruction.rs` | All IR instruction variants |
| IR Types | `src/irtype.rs` | IR type system (flat, no generics) |
| Values | `src/value.rs` | SSA values: instructions + constants |
| Constants | `src/constant.rs` | Compile-time constants |
| Pass Manager | `src/pass_manager.rs` | Pass ordering and execution |
| Analyses | `src/analysis/` | Dominators, use-def chains, call graph |
| Passes | `src/passes/` | One file per optimization pass |
| Printer | `src/printer.rs` | IR to text format |
| Parser | `src/parser.rs` | Text format to IR (for tests) |
| IR Macros | `sway-ir-macros/` | Proc-macros for IR construction in tests |

#### `sway-error`

```rust
// Core types in sway-error
pub struct Handler {
    inner: RefCell<HandlerInner>,
}

pub struct HandlerInner {
    pub errors: Vec<(Span, CompileError)>,
    pub warnings: Vec<CompileWarning>,
}

pub struct ErrorEmitted;  // Zero-size type; returned from functions that emit errors
```

The `Handler` is passed through every compilation phase. Errors are collected
(not immediately fatal) allowing multiple errors to be reported per build. An
`Err(ErrorEmitted)` return means at least one error was emitted to the handler;
the caller can continue or propagate.

#### `sway-features`

```rust
pub struct ExperimentalFeatures {
    pub new_encoding: bool,
    pub references: bool,
    pub new_hashing: bool,
    pub str_array_no_padding: bool,
    pub dynamic_storage: bool,
}

impl ExperimentalFeatures {
    // Reads FORC_EXPERIMENTAL and FORC_NO_EXPERIMENTAL env vars
    pub fn from_env() -> Self { ... }
    
    // Construct with all features disabled
    pub fn none() -> Self { ... }
}
```

#### `sway-types`

| Type | Description |
|---|---|
| `Span` | Source location: `SourceId` + byte start + byte end |
| `Ident` | Identifier string + `Span` |
| `SourceId` | Opaque file identifier (integer) |
| `SourceEngine` | Maps `SourceId` ↔ file path and full source content |
| `Spanned` | Trait: `fn span(&self) -> Span` |
| `Named` | Trait: `fn name(&self) -> &Ident` |

#### `sway-utils`

Key constants:
```rust
pub const MANIFEST_FILE_NAME: &str = "Forc.toml";
pub const MAIN_ENTRY: &str = "main.sw";
pub const LIB_ENTRY: &str = "lib.sw";
pub const DEFAULT_OUTPUT_DIRECTORY: &str = "out";
pub const LOCK_FILE_NAME: &str = "Forc.lock";
pub const SWAYFMT_CONFIG_FILE_NAME: &str = "swayfmt.toml";
```

Key functions:
```rust
// Search upward from starting_directory for Forc.toml
pub fn find_manifest_dir(starting_directory: &Path) -> Option<PathBuf>

// Search upward for workspace root (Forc.toml with [workspace])
pub fn find_workspace_dir(starting_directory: &Path) -> Option<PathBuf>
```

#### `swayfmt`

| Module | Description |
|---|---|
| `src/config/` | All configuration type definitions and defaults |
| `src/formatter/` | Core formatting state machine and entry points |
| `src/utils/comments/` | Comment preservation and correct placement |
| `src/utils/expressions/` | Expression formatting rules |
| `src/utils/heuristics/` | Width-based line-break decisions |
| `src/utils/imports/` | `use` statement formatting and grouping |
| `src/utils/items/` | Item (declaration) formatting |
| `src/utils/literals/` | Literal value formatting |
| `src/utils/ordering/` | Item ordering within module scope |
| `src/utils/structures/` | Struct and enum formatting |
| `src/utils/whitespace/` | Indentation and newline normalization |

Public API:
```rust
pub fn format_text(src: &Arc<str>) -> Result<String, FormatterError>

pub fn format_text_with_config(
    src: &Arc<str>,
    config: &FormatterConfig,
) -> Result<String, FormatterError>
```

#### `sway-lsp`

| Component | Description |
|---|---|
| `src/server.rs` | `tower-lsp` `LanguageServer` trait implementation |
| `src/capabilities.rs` | LSP `ServerCapabilities` construction |
| `src/core/session.rs` | Per-workspace compilation session (holds typed program) |
| `src/core/document.rs` | Per-file text document state and version tracking |
| `src/handlers/` | Individual LSP request handlers |
| `src/traverse/` | Post-compilation AST traversal for IDE feature queries |

Concurrency model: `dashmap::DashMap` provides lock-free concurrent access to
the document store and session state. Read-heavy operations (hover, completion,
diagnostics) proceed without blocking; the compilation lock serializes write
access to the typed program state.

#### `forc`

```
forc/src/
  main.rs              Jemalloc setup, async runtime, CLI dispatch
  cli/
    mod.rs             Subcommand enum and dispatch table
    build.rs           forc build
    check.rs           forc check
    clean.rs           forc clean
    new.rs             forc new / forc init
    deploy.rs          forc deploy
    run.rs             forc run
    test.rs            forc test
    update.rs          forc update
    add.rs             forc add
    remove.rs          forc remove
    contract_id.rs     forc contract-id
    parse_bytecode.rs  forc parse-bytecode
    completions.rs     forc completions
    plugins.rs         forc plugins
    addr2line.rs       forc addr2line
```

#### `forc-pkg`

| Component | Description |
|---|---|
| `src/manifest/` | `Forc.toml` parsing, validation, workspace detection |
| `src/lock.rs` | `Forc.lock` reading and writing |
| `src/source/` | Dependency fetching: `path/`, `git/`, `ipfs/` |
| `src/pkg.rs` | Package compilation orchestration |
| `src/build_plan.rs` | Dependency DAG construction, topological sort |
| `src/compiled_package.rs` | Compiled package artifact type |
| `src/lib.rs` | Public API |

The dependency graph is a `petgraph::Graph<Node, Edge>`. Topological ordering
via `petgraph::algo::toposort` determines build order. Cycle detection uses
`petgraph::algo::is_cyclic_directed`.

#### `forc-test`

Implements the Sway unit test runner:
1. Compiles the package with test functions enabled
2. Deploys the contract to an in-process FuelVM instance
3. Calls each `#[test]` function as an ABI method
4. Reports pass/fail based on whether the call reverts

#### `forc-util`

| Component | Description |
|---|---|
| Bytecode parsing | Disassembly of FuelVM `.bin` bytecode |
| CLI utilities | Shared `clap` arg types, error formatting |
| Node connection | Shared fuel-core-client setup |

#### `forc-debug`

Implements the DAP server. Main loop:
1. Start tokio async runtime
2. Connect to Fuel node GraphQL endpoint (`--api-url`)
3. Listen on stdin for DAP protocol messages (JSON-RPC)
4. Translate DAP requests (set-breakpoint, step, continue) to Fuel node debug API calls
5. Send DAP events (stopped, output) back on stdout

#### `forc-doc`

1. Compiles the package with `forc-pkg`
2. Walks the typed AST for all public items (functions, structs, enums, traits)
3. Extracts doc comments (`///` and `//!`)
4. Generates HTML pages using `horrorshow` macros
5. Writes output to `out/doc/`

#### `forc-migrate`

For each defined migration:
1. Scan source files for patterns matching the deprecated form
2. Apply AST-aware or regex-based transforms
3. Write modified files (or preview in `--dry-run`)
4. Report what was changed

#### `forc-publish`

1. Validate `Forc.toml` (required fields)
2. Run `forc check` to ensure the package type-checks
3. Create a source tarball (excluding build artifacts and `.forc/`)
4. Upload to the registry via HTTP using `FORC_PUB_TOKEN`

### 8.4 Error Message Taxonomy

The compiler emits **295 distinct diagnostic types** across all phases, split
between hard errors (`CompileError`) and warnings (`CompileWarning`).

#### Parse Error Categories

| Category | Approx Count | Representative Messages |
|---|---|---|
| Unexpected token | ~15 | `UnexpectedToken`, `ExpectedToken`, `UnexpectedEndOfInput` |
| Invalid literal | ~8 | `InvalidIntegerLiteral`, `InvalidHexLiteral`, `InvalidStrEscape` |
| Invalid syntax | ~20 | Misplaced keywords, invalid attribute syntax, bad annotation |
| Delimiter mismatch | ~5 | Unclosed braces, mismatched parentheses, extra closing delimiter |

#### Type Error Categories

| Category | Approx Count | Representative Messages |
|---|---|---|
| Type mismatch | ~25 | `TypeError`, `MismatchedType`, `ArgumentParameterTypeMismatch` |
| Unresolved type | ~15 | `UnresolvedType`, `UnknownType`, `UnableToInferGeneric` |
| Generic constraint violation | ~12 | `TraitConstraintNotSatisfied`, `TraitNotImplemented` |
| Array/slice errors | ~8 | `InvalidArrayLength`, `ArrayOutOfBounds`, `ConstantEvaluationError` |
| Integer range/cast | ~6 | `IntegerTooLarge`, `IntegerOverflow`, `TypeCastNotAllowed` |
| Self type errors | ~5 | `InvalidSelfParam`, `SelfParameterNotAllowedForContract` |
| Numeric type errors | ~6 | `MultipleDefinitionsOfName`, `UnreachablePattern` |

#### Declaration Error Categories

| Category | Approx Count | Representative Messages |
|---|---|---|
| Duplicate declaration | ~12 | `DuplicateDeclaration`, `MultipleDefinitionsOfName` |
| Missing declaration | ~10 | `SymbolNotFound`, `FunctionNotFound`, `MethodNotFound` |
| Visibility errors | ~8 | `ModuleNotFound`, `PrivateField`, `ImportPrivateModule` |
| Trait/impl errors | ~15 | `MissingInterfaceSurfaceMethods`, `ImplSelfWithoutSelf`, `TraitImplNotAllowed` |
| Storage errors | ~12 | `InvalidStorageField`, `StorageAccessMismatch`, `StorageNotDeclared` |

#### Control Flow Error Categories

| Category | Approx Count | Representative Messages |
|---|---|---|
| Unreachable code | ~5 | `UnreachableCode`, `MatchPatternAlreadyCovered` |
| Missing return | ~3 | `MissingReturnStatement`, `ReturnStatementNotAllowed` |
| CEI violation | ~4 | `StorageWriteAfterContractCall` |
| Loop issues | ~2 | `BreakOutsideLoop`, `ContinueOutsideLoop` |

#### ABI Error Categories

| Category | Approx Count | Representative Messages |
|---|---|---|
| Invalid ABI type | ~8 | `InvalidABIType`, `ABIMethodNotFound`, `ABISupertraitNotABI` |
| ABI encoding | ~6 | `InvalidEncodingType`, `ABIHashTemplateError` |

#### Code Generation Error Categories

| Category | Approx Count | Representative Messages |
|---|---|---|
| Register allocation | ~5 | `TooManyRegisters` |
| Unsupported operation | ~10 | `OperationNotSupported`, `TargetNotSupported` |
| IR errors | ~8 | `IrGenError`, `IsizeTooBig` |

#### Warning Categories

| Category | Approx Count | Representative Messages |
|---|---|---|
| Dead code | ~8 | `DeadCode`, `UnusedVariable`, `UnusedImport`, `UnusedReturnValue` |
| Deprecated usage | ~5 | `Deprecated` |
| Style | ~3 | `NonSnakeCaseStructFieldName`, `NonCamelCaseTypeName` |
| CEI pattern | ~4 | `StorageWriteAfterContractCall` |
| Shadow warning | ~3 | `ShadowsOtherSymbol` |

### 8.5 Storage Layout Reference

```sway
storage {
    // Simple field: key = sha256("storage_domain:owner")
    owner: Address = Address::zero(),

    // Map: key for entry k = sha256(sha256("storage_domain:balances") ++ k)
    balances: StorageMap<Address, u64> = StorageMap::<Address, u64> {},

    // Vec: element i key = sha256(sha256("storage_domain:items") ++ i)
    items: StorageVec<u64> = StorageVec {},

    // Nested: StorageVec<StorageMap<...>> — see issue #6040 for limitations
}
```

Storage keys are **deterministic** and **collision-resistant** by construction:
- Each storage field has a unique domain derived from its name
- Map keys are hashed with the field domain, preventing aliasing
- Vec indices are hashed with the field domain

Active storage bugs:
- **#6040** — `StorageVec::insert()` with deeply nested generic types
- **#7559** — Complex generic `StorageKey<T>` fails to resolve in certain patterns

### 8.6 Testing Infrastructure

#### Test Infrastructure Overview (`test/` crate)

The `test` workspace member is the E2E test harness. Each test case is a
Sway project in `tests/` with a `test.toml` controlling behavior.

#### test.toml Format

```toml
# Category controls what the harness does with this test
category = "run"           # run | run_on_node | compile | unit_tests_pass | fail | disabled

# For "run" and "run_on_node" categories:
expected_output = "42\n"   # Expected stdout from script execution

# For "fail" category:
# (errors are checked against .stderr expected files)
```

| Category | Description |
|---|---|
| `run` | Compile and execute; assert stdout matches `expected_output` |
| `run_on_node` | Compile and run against a live `fuel-core` node |
| `compile` | Compile only; assert success (or failure for `expected_failure`) |
| `unit_tests_pass` | Compile and run all `#[test]` functions; assert all pass |
| `fail` | Assert compilation fails with specific errors |
| `disabled` | Skip; comment in `test.toml` explains why |

#### Snapshot Tests

`snapshot.toml` drives compilation commands. Expected output is stored in
`.expected` files adjacent to each test project.

```bash
# Run snapshot tests
cargo test --package test -- snapshot

# Update snapshots (when output intentionally changes)
UPDATE_EXPECT=1 cargo test --package test -- snapshot
```

#### In-Language Unit Tests

```sway
contract;

#[test]
fn addition_works() {
    assert_eq(1u64 + 1u64, 2u64);
}

#[test]
fn zero_division_reverts() {
    let _ = 1u64 / 0u64;  // should revert
}

#[test(should_revert)]
fn expected_revert() {
    revert(42);
}
```

Run with `forc test`. Harness compiles the package with tests enabled,
deploys to an in-process VM, and calls each test function.

#### SDK Harness Tests (Rust)

```rust
use fuels::prelude::*;

// abigen! generates Rust bindings from the ABI JSON
abigen!(Contract(
    name = "MyToken",
    abi = "out/debug/my_token-abi.json"
));

#[tokio::test]
async fn test_mint() {
    let config = WalletsConfig::new(Some(1), None, None);
    let wallets = launch_custom_provider_and_get_wallets(config, None, None)
        .await
        .unwrap();
    let wallet = wallets.into_iter().next().unwrap();

    let id = Contract::load_from(
        "out/debug/my_token.bin",
        LoadConfiguration::default(),
    )
    .unwrap()
    .deploy(&wallet, TxPolicies::default())
    .await
    .unwrap();

    let contract = MyToken::new(id, wallet);
    let result = contract
        .methods()
        .mint(100u64)
        .call()
        .await
        .unwrap();
    assert_eq!(result.value, 100u64);
}
```

#### Performance Test Recipes

```bash
just perf-e2e          # Compile ~20 representative contracts; measure wall time
just perf-in-lang      # Run in-language tests; measure execution time
just perf-all          # Both of the above
just perf-diff         # Compare vs saved baseline (stored in perf_baseline/)
just perf-diff-latest  # Compare vs forc downloaded from latest GitHub release
```

### 8.7 Contributing — Development Workflow

#### First-Time Setup

```bash
git clone https://github.com/FuelLabs/sway.git && cd sway
rustup show                    # Installs pinned toolchain from rust-toolchain.toml
cargo install cargo-sort just  # Required by CI
cargo build --workspace        # Initial build
cargo test --workspace         # Run full test suite
```

#### CI Requirements (All Must Pass)

```bash
cargo sort --check --workspace      # Sorted [dependencies] in all Cargo.toml
cargo fmt --check --all             # Rust formatting
cargo clippy --all-targets \
  --workspace -- -D warnings        # No clippy warnings
forc fmt --check                    # Sway example formatting
cargo build --workspace             # Full build
cargo test --workspace              # Full test suite
```

#### Adding a Language Feature (Step-by-Step)

1. **AST nodes** (`sway-ast`): Add new `Item*`, `Expr*`, or `Ty*` variants with
   `Span` fields
2. **Parser** (`sway-parse`): Extend the relevant recursive descent rule to produce
   the new node; add `ParseToEnd`/`ParseBracket` combinators as needed
3. **Typed AST** (`sway-core/language/`): Add corresponding typed variants; these
   hold `TypeId` instead of raw syntax types
4. **Type checker** (`sway-core/type_system/`): Implement type-checking logic for
   the new node; use the `Engines` struct to access `TypeEngine` and `DeclEngine`
5. **IR lowering** (`sway-core/ir_generation/`): Emit appropriate `sway-ir`
   instructions for the new construct
6. **Tests**: Add test cases in `tests/` covering both success and expected-failure
   scenarios; add a `test.toml` for each
7. **Book**: Update `docs/book/` with user-facing documentation
8. **Errors**: If the feature introduces new error conditions, add variants to
   `sway-error`

#### Adding an IR Optimization Pass

1. Create `sway-ir/src/passes/my_pass.rs`
2. Implement `Pass`:
   ```rust
   pub struct MyPass;
   impl Pass for MyPass {
       fn name(&self) -> &str { "my-pass" }
       fn descr(&self) -> &str { "Describe what this pass does" }
       fn run(&self, module: &mut Module, _: &AnalysisResults) -> Result<bool, IrError> {
           // Modify IR; return Ok(true) if any change was made
           Ok(false)
       }
       fn analyses_required(&self) -> Vec<AnalysisName> { vec![] }
   }
   ```
3. Register in `sway-ir/src/pass_manager.rs`
4. Add tests in `sway-ir/tests/` using the text IR parser

#### Filing a High-Quality Bug Report

```bash
# Capture the panic with full backtrace
RUST_BACKTRACE=full forc build --path /path/to/reproducer 2>&1 > bug_report.txt

# Note exact versions
forc --version >> bug_report.txt
rustc --version >> bug_report.txt

# Minimize the reproducer
# Remove code until the panic stops, then restore the last line removed
```

Include in the GitHub issue:
- `forc --version` output
- `RUST_BACKTRACE=full` output
- Minimal self-contained Sway project that reproduces the issue
- Operating system and architecture

#### Active High-Priority Issues for Contributors

| Issue | Title | Severity |
|---|---|---|
| #7551 | Compiler infinite loop | Critical |
| #7603 | ICE from invalid type unification of arrays | High |
| #7604 | Compiler panic with type aliases + const generic arrays | High |
| #7602 | ICE when accessing `self[i]` with const generics | High |
| #7606 | CEI warnings nondeterministic | Medium |
| #7605 | Confusing OOB error for const generic arrays | Medium |
| #6040 | `StorageVec::insert()` with nested types | Medium |
| #7559 | Generic `StorageKey` resolution failure | Medium |
| #7589 | RUSTSEC-2025-0055 ANSI escape log poisoning | Low |
| #7576 | RUSTSEC-2026-0049 CRL matching logic flaw | Low |

### 8.8 LSP Architecture Deep Dive

The `sway-lsp` server follows a session-based architecture to maintain
workspace state across editor interactions:

```
Editor (VS Code, Neovim, Emacs, ...)
  ↕ JSON-RPC 2.0 (stdin/stdout, per LSP spec)
  ↕ Managed by tower-lsp framework
LSP Server Process (forc lsp → sway-lsp)
  ├── Compilation loop (triggered by textDocument/didSave)
  │     ├── forc-pkg: resolve dependencies
  │     ├── sway-parse: parse changed files
  │     ├── sway-core: type check, build typed program
  │     └── Update session state
  └── Request handlers (hover, completion, definition, references, ...)
        └── Query session state (read-only, concurrent via DashMap)
```

**Performance design:**
- Compilation is triggered only on `textDocument/didSave`, not on every
  keystroke. This keeps compile overhead from blocking typing.
- Between saves, all IDE requests (hover, completion, go-to-definition) use
  cached session state. These complete in O(1) to O(log n) with no compilation.
- `DashMap` allows multiple concurrent readers, so parallel LSP requests
  (e.g., hover + diagnostics publication) do not block each other.

**Span-based query architecture:**
All IDE features are implemented by:
1. Converting the cursor position (line, column) to a byte offset
2. Finding the `Span` in the typed AST that covers the cursor offset
3. Querying the declaration engine for what that span refers to
4. Returning the relevant information (type, documentation, location)

### 8.9 ABI Format Reference

#### Fuel JSON ABI (Full Structure)

```json
{
  "specVersion": "1",
  "encodingVersion": "1",
  "programType": "contract",
  "concreteTypes": [
    {
      "type": "u64",
      "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0",
      "metadataTypeId": 0,
      "components": null,
      "typeParameters": null
    }
  ],
  "metadataTypes": [
    {
      "type": "u64",
      "metadataTypeId": 0,
      "components": null,
      "typeParameters": null
    }
  ],
  "functions": [
    {
      "name": "transfer",
      "inputs": [
        { "name": "amount", "concreteTypeId": "..." },
        { "name": "recipient", "concreteTypeId": "..." }
      ],
      "output": "...",
      "attributes": ["storage(read, write)", "payable"]
    }
  ],
  "loggedTypes": [
    { "logId": "0", "concreteTypeId": "..." }
  ],
  "messagesTypes": [...],
  "configurables": [
    {
      "name": "OWNER",
      "concreteTypeId": "...",
      "offset": 2048
    }
  ]
}
```

#### Function Selector Computation

```
selector = SHA-256( canonical_signature )[0..4]
```

Where `canonical_signature` follows the pattern:
```
function_name(param1_type,param2_type,...)
```

Example:
```
transfer(u64,b256) → SHA-256("transfer(u64,b256)")[0..4]
```

---

## 9. Integration Points

### 9.1 Fuel Node Integration

`forc` communicates with `fuel-core` nodes via the GraphQL API, using the
`fuel-core-client` (v0.48.0) crate:

| Operation | How |
|---|---|
| `forc deploy` | Submits a `Create` transaction containing bytecode + storage slots |
| `forc run` | Submits a `Script` transaction; prints output |
| `forc test` (E2E) | Launches ephemeral in-process node; submits transactions; asserts results |
| `forc debug` | Streams debug events via DAP over the node's debug interface |

Default node URL: `http://127.0.0.1:4000/graphql`

Override in any command:

```bash
forc deploy --node-url http://beta-5.fuel.network/graphql
forc run --node-url http://testnet.fuel.network/graphql
forc test --node-url http://127.0.0.1:4000/graphql
```

### 9.2 Fuel Rust SDK Integration (`fuels` 0.77)

The `fuels` crate is the primary SDK for writing Rust integration tests against
compiled Sway contracts. The workflow:

1. `abigen!` macro reads the ABI JSON and generates type-safe Rust bindings
2. `Contract::load_from()` loads the compiled `.bin` bytecode
3. `.deploy()` submits a `Create` transaction to the node
4. Generated methods call contract functions via ABI-encoded `Script` transactions
5. Return values are ABI-decoded back to Rust types

```rust
use fuels::prelude::*;

abigen!(Contract(
    name = "MyContract",
    abi = "out/debug/my_contract-abi.json"
));

#[tokio::test]
async fn integration_test() {
    // Launch an in-process fuel-core node with a funded wallet
    let config = WalletsConfig::new(Some(1), Some(1), Some(Amount::from(1_000_000)));
    let wallets = launch_custom_provider_and_get_wallets(config, None, None)
        .await
        .unwrap();
    let wallet = wallets.into_iter().next().unwrap();

    // Deploy
    let id = Contract::load_from(
        "out/debug/my_contract.bin",
        LoadConfiguration::default(),
    )
    .unwrap()
    .deploy(&wallet, TxPolicies::default())
    .await
    .unwrap();

    // Call
    let contract_instance = MyContract::new(id, wallet);
    let result = contract_instance
        .methods()
        .my_function(42u64)
        .call()
        .await
        .unwrap();
    assert_eq!(result.value, 42u64);
}
```

### 9.3 mdBook Integration

The Sway book is built with `mdbook` plus the custom `mdbook-forc-documenter`
preprocessor (in `scripts/mdbook-forc-documenter/`). This preprocessor
generates `forc` subcommand documentation pages directly from the `clap`
argument definitions, keeping the book in sync with the tool automatically.

```bash
# Install dependencies
cargo install mdbook
cargo install --path scripts/mdbook-forc-documenter

# Build the book
mdbook build docs/book
# Output: docs/book/book/

# Serve locally with hot-reload
mdbook serve docs/book --open
```

The book is also published to the Fuel documentation site on each release.

### 9.4 Editor Integration

#### Visual Studio Code

Install the official **Sway** extension (by FuelLabs) from the VS Code
marketplace. Configuration in `settings.json`:

```json
{
  "sway.server.path": "forc",      // Uses forc lsp subcommand
  "sway.trace.server": "off",      // "off" | "messages" | "verbose"
  "editor.formatOnSave": true,
  "[sway]": {
    "editor.defaultFormatter": "FuelLabs.sway-vscode-plugin"
  }
}
```

#### Neovim (nvim-lspconfig)

```lua
require('lspconfig').sway_lsp.setup({
  cmd = { 'forc', 'lsp' },
  filetypes = { 'sway' },
  root_dir = require('lspconfig').util.root_pattern('Forc.toml'),
  settings = {},
  on_attach = function(client, bufnr)
    -- Standard LSP keybindings
    local opts = { buffer = bufnr }
    vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
    vim.keymap.set('n', 'K',  vim.lsp.buf.hover, opts)
    vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts)
  end,
})
```

#### Emacs (eglot or lsp-mode)

```emacs-lisp
;; eglot
(add-to-list 'eglot-server-programs
             '(sway-mode . ("forc" "lsp")))

;; lsp-mode
(lsp-register-client
  (make-lsp-client
    :new-connection (lsp-stdio-connection '("forc" "lsp"))
    :major-modes '(sway-mode)
    :server-id 'sway-lsp))
```

### 9.5 DAP Debugging Integration

`forc-debug --serve` implements the Debug Adapter Protocol over stdin/stdout.
The IDE launches `forc debug --serve` as a child process and communicates
via DAP JSON-RPC.

VS Code `launch.json` example:

```json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "fuel",
      "request": "launch",
      "name": "Debug Sway Script",
      "program": "${workspaceFolder}/out/debug/my_script.bin",
      "nodeUrl": "http://127.0.0.1:4000/graphql",
      "stopAtEntry": true
    }
  ]
}
```

Neovim (`nvim-dap`):

```lua
local dap = require('dap')
dap.adapters.fuel = {
  type = 'executable',
  command = 'forc',
  args = { 'debug', '--serve' },
}
dap.configurations.sway = {
  {
    type = 'fuel',
    request = 'launch',
    name = 'Debug contract',
    program = '${workspaceFolder}/out/debug/my_contract.bin',
    nodeUrl = 'http://127.0.0.1:4000/graphql',
  },
}
```

### 9.6 IPFS Dependency Integration

```toml
# Forc.toml
[dependencies]
my_library = { ipfs = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG" }
```

```bash
# Override IPFS gateway
forc build --ipfs-node https://ipfs.infura.io

# Use Cloudflare IPFS gateway
forc build --ipfs-node https://cloudflare-ipfs.com
```

IPFS packages are cached in `~/.forc/cache/ipfs/<cid>/` after first fetch.
Content is verified by CID (content-addressed, so integrity is implicit).

### 9.7 Downstream Tooling Compatibility

| Tool | Input | Description |
|---|---|---|
| `fuel-core` | `.bin` bytecode, ABI JSON | Executes contracts and scripts |
| `fuels-rs` | ABI JSON | `abigen!` generates Rust bindings |
| `fuels-ts` | ABI JSON | Generates TypeScript/JavaScript bindings |
| `fuel-explorer` | ABI JSON, debug info | Block explorer contract verification |
| Sway Playground | Source code | Web-based Sway IDE (online) |

### 9.8 Troubleshooting Reference

> [!WARNING]
> The following ICE (Internal Compiler Error) patterns correspond to active
> bugs in version **0.71.0** (commit `e12e611`). Track the linked issues for
> fix status.

| Symptom | Likely Cause | Issue | Workaround |
|---|---|---|---|
| Panic / ICE during type checking with type aliases | Type alias + const generic array | #7604 | Avoid const generics on type-aliased types |
| ICE on `self[i]` access | Const generic indexing edge case | #7602 | Use explicit index variable with known type |
| ICE "invalid type unification" message | Array type unification scope escape | #7603 | Simplify array type expressions |
| `forc build` hangs indefinitely | Infinite loop in type inference | #7551 | Kill process; file issue with minimal reproducer |
| CEI warning appears or disappears non-deterministically | Nondeterministic CEI analysis | #7606 | Treat any CEI occurrence as real; apply manual review |
| Confusing "out of bounds" error on const generic array | Incorrect error reporting path | #7605 | Check array size bounds carefully; compare type signatures |
| `StorageVec` behaves incorrectly with nested types | Nested type storage layout bug | #6040 | Avoid `StorageVec<StorageMap<...>>` and similar patterns |
| Generic `StorageKey<T>` fails to compile in complex patterns | Generic storage key resolution | #7559 | Simplify storage generic parameters |
| Terminal shows garbled output in CI | ANSI escape log poisoning | #7589 | Strip ANSI codes from output; see §7.1 |
| `forc build` fetches dependencies despite `--offline` | CRL validation dependency | #7576 | Use `--locked --offline`; verify `Forc.lock` is committed |

> [!NOTE]
> For issues not in the table above, search https://github.com/FuelLabs/sway/issues
> before filing a new report. Always include `forc --version`, `RUST_BACKTRACE=full`
> output, and a minimal self-contained reproducer.

---

_Generated May 2026 from FuelLabs/sway at e12e611. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
