Skip to content

Commit 4d6fa3c

Browse files
Add experimental design workflow documentation files in .exp/
1 parent 9e970d7 commit 4d6fa3c

12 files changed

+1177
-0
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# High-Level Design of Workflow #1: cargo-clippy
2+
3+
## Overview
4+
5+
The \"cargo-clippy\" workflow enables running Clippy as a Cargo subcommand (`cargo clippy`) to lint Rust code in Cargo projects, including workspaces and optionally dependencies. It catches common mistakes, suggests improvements, and can auto-fix issues via `--fix`.
6+
7+
This workflow wraps Cargo's `check` or `fix` commands, injecting Clippy into the Rust compiler pipeline by setting `RUSTC_WORKSPACE_WRAPPER` to `clippy-driver` and passing Clippy-specific arguments via `CLIPPY_ARGS`. During compilation, Clippy's lints are registered and executed at various stages (AST, HIR, MIR), emitting diagnostics based on configuration from CLI, `clippy.toml`, and code attributes.
8+
9+
Inputs include project directory (Cargo.toml), flags (e.g., `--all-targets`, `--fix`), env vars (e.g., `RUSTFLAGS`), and config files. Outputs are lint messages, potential source modifications, and exit codes.
10+
11+
Entry point: `src/main.rs` (cargo-clippy binary).
12+
13+
## Components
14+
15+
- **cargo-clippy (`src/main.rs`)**: Handles CLI parsing, determines subcommand (`check` or `fix` based on `--fix`), constructs environment variables, and spawns `cargo` process.
16+
17+
- **clippy-driver (`src/driver.rs`)**: Custom Rust compiler driver extending `rustc_driver`. Uses `ClippyCallbacks` to:
18+
- Load configuration.
19+
- Register Clippy lints with the `LintStore`.
20+
- Adjust compiler options (e.g., `mir_opt_level = 0` for unoptimized MIR analysis, disable certain passes).
21+
- Track dependencies (e.g., `clippy.toml`, `CLIPPY_ARGS`) for Cargo rebuild triggers.
22+
23+
- **clippy_lints**: Core library implementing ~750 lints.
24+
- `declared_lints::LINTS`: Array of all lint metadata.
25+
- Modular implementations in submodules (e.g., `methods/`, `misc_early/`, `operators/`).
26+
- `register_lint_passes(store, conf)`: Registers `rustc_lint::LintPass` instances, filtered by config.
27+
28+
- **clippy_config**: Parses hierarchical configuration from `clippy.toml` files, inline attributes (`#[allow(clippy::lint)]`), and CLI flags to set lint levels (allow, warn, deny, forbid) and groups.
29+
30+
- **clippy_utils**: Utilities for lint authors, including AST/HIR/MIR queries, type comparisons, symbol matching, etc., to share common logic.
31+
32+
- **rustc_tools_util**: Provides version information, environment setup helpers, and utilities for interacting with Rustc internals.
33+
34+
- **declare_clippy_lint**: Macro crate for declaring lint structs with metadata (name, level, description, etc.).
35+
36+
## Sequence Diagram
37+
38+
The following Mermaid sequence diagram illustrates the primary flow of information and control in the cargo-clippy workflow:
39+
40+
```mermaid
41+
sequenceDiagram
42+
participant U as User
43+
participant CC as "cargo-clippy"
44+
participant C as cargo
45+
participant CD as "clippy-driver"
46+
participant RI as rustc_interface
47+
participant LS as "Lint Store"
48+
participant CL as "Clippy Lints (clippy_lints)"
49+
participant Config as "clippy_config"
50+
51+
U->>CC: cargo clippy [options]
52+
Note right of CC: Parse args, set mode (check/fix)<br/>Set env vars: RUSTC_WORKSPACE_WRAPPER, CLIPPY_ARGS
53+
CC->>C: cargo check/fix [user args]
54+
C->>CD: Invoke as rustc for each compilation unit
55+
CD->>RI: rustc_driver::run_compiler(args, ClippyCallbacks)
56+
RI->>CD: Callbacks::config(config)
57+
CD->>Config: load_conf() -> clippy.toml, attributes
58+
Config-->>CD: Conf (enabled lints, levels)
59+
Note right of CD: Adjust opts: mir_opt_level=0,<br/>disable some MIR passes, etc.
60+
CD->>LS: register_lints(sess, store)
61+
LS->>CL: Register declared_lints::LINTS
62+
CL-->>LS: Lint metadata registered
63+
LS->>CL: clippy_lints::register_lint_passes(store, conf)
64+
CL-->>LS: LintPass instances registered (filtered by conf)
65+
Note over RI: Compilation pipeline executes:<br/>- Parse to AST<br/>- Expand/lower to HIR<br/>- MIR construction<br/>- At each phase, applicable lints run via visitors/checkers
66+
alt --fix mode
67+
Note over CL,RI: Lints emit rustfix suggestions
68+
RI->>C: Suggestions via compiler interface
69+
C->>U: cargo fix applies to source files
70+
else check mode
71+
RI->>U: Print diagnostics to stdout/stderr
72+
end
73+
```
74+
75+
## Configuration and Customization
76+
77+
- **Loading**: In `clippy-driver`, `clippy_config::Conf::read()` aggregates config from:
78+
- Project-local `clippy.toml`.
79+
- Ancestor directories.
80+
- Code attributes.
81+
- CLI flags passed via `CLIPPY_ARGS` (e.g., `-W clippy::perf`).
82+
- **Application**: Used to filter and level lints during registration. Supports groups (correctness, style, perf, etc.) and MSRV specifications.
83+
- **Tracking**: Config files and env vars are added to `ParseSess`'s depinfo for incremental builds.
84+
85+
## Lint Execution Details
86+
87+
- **Phases**: Lints are categorized and run at specific compiler stages:
88+
- Early (pre-type-check): AST visitors in `misc_early/`.
89+
- Post-type-check: HIR/MIR analyses in other modules.
90+
- **Implementation**: Each lint is a struct implementing `rustc_lint::LintPass` (or early variant), defining `get_lints()` and visitor/check methods.
91+
- **Diagnostics**: Emit via `sess.emit_warning()`, `emit_error()`, etc., with spans, explanations, and optional fixes.
92+
- **Fixes**: Many lints integrate with `rustfix` for `--fix` mode, generating edit suggestions applied by `cargo fix`.
93+
94+
## Additional Design Aspects
95+
96+
- **Wrapper Mode Handling**: `clippy-driver` detects if invoked as `rustc` wrapper (via Cargo) and adjusts args. Supports direct invocation or delegation (`--rustc`).
97+
- **Optimization Trade-offs**: Disables optimizations like MIR passes and format_args flattening for accurate linting, potentially increasing compile time.
98+
- **Skip Conditions**: Bypasses Clippy for Cargo metadata queries, cap-lints=allow (unless forcing Clippy), or irrelevant packages in --no-deps mode.
99+
- **Error Reporting**: Integrates with rustc's diagnostics; ICEs report to GitHub issues with version info.
100+
- **Development Features**: Tracks driver executable in debug mode for rebuilds during development.
101+
- **Dependencies**: Relies on `rustc_private` for compiler internals; must sync with Rust releases.
102+
103+
This design provides tight integration with the Rust toolchain, enabling powerful static analysis while maintaining Cargo compatibility.
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# High-Level Design of the clippy-driver Workflow
2+
3+
## Overview
4+
5+
The clippy-driver workflow enables direct invocation of Clippy as a Rust compiler driver, providing an interface similar to \`rustc\` for linting individual Rust source files (.rs) or crates in non-Cargo environments, such as custom build scripts, IDE integrations, or standalone analysis tools. It serves as the core execution engine behind \`cargo clippy\` (via the \`RUSTC_WRAPPER\` environment variable) but can be run independently.
6+
7+
Key characteristics:
8+
- **Inputs**: Rust source files, rustc-compatible CLI arguments (e.g., \`--edition\`, \`--target\`), optional sysroot, configuration via \`clippy.toml\` or env vars like \`CLIPPY_ARGS\`.
9+
- **Outputs**: Lint diagnostics (warnings, errors, suggestions) emitted to stdout/stderr, optional compiled artifacts (e.g., binaries, LLVM IR) if compilation proceeds.
10+
- **Entry Point**: \`src/driver.rs\` – processes arguments, decides on Clippy activation, and orchestrates the compilation via \`rustc_driver\`.
11+
- **Core Mechanism**: Acts as a drop-in replacement for \`rustc\`, customizing the compiler session to register Clippy's lints, adjust optimization levels (e.g., MIR opt level 0 for precise analysis), and execute analysis passes during compilation phases.
12+
- **Decision Logic**: Skips Clippy lints if all are capped to \`allow\` or in certain Cargo info queries; falls back to plain \`rustc\` behavior.
13+
- **Dependencies**: Leverages \`clippy_lints\` for lint implementations, \`clippy_utils\` for analysis helpers, and \`clippy_config\` for settings.
14+
15+
This workflow ensures deep integration with Rust's compiler pipeline, allowing lints to access internal representations (AST, HIR, MIR, TyCtxt) for sophisticated checks impossible in external tools.
16+
17+
## Components
18+
19+
- **Argument Processing (src/driver.rs)**: Parses CLI args using \`rustc_driver::args::raw_args\`, handles special modes (\`--rustc\` delegates to rustc, \`--help\`/\`--version\`), injects Clippy-specific flags (e.g., \`--cfg clippy\`) from \`CLIPPY_ARGS\`.
20+
- **Callbacks (ClippyCallbacks / RustcCallbacks)**: Implement \`rustc_driver::Callbacks\`; customize config (lint registration, unstable opts), session creation (dependency tracking for Cargo rebuilds, e.g., Cargo.toml, clippy-driver exe).
21+
- **Lint Registry (clippy_lints/src/lib.rs)**: \`register_lint_passes\` populates \`rustc_lint::LintStore\` with:
22+
- Deprecated/renamed/removed lints.
23+
- Pre-expansion passes (e.g., attribute collection).
24+
- Early passes (AST/HIR-based, e.g., formatting, doc checks).
25+
- Late passes (typed analysis, e.g., type checks, method calls).
26+
- Supports conditional enabling via \`Conf\`.
27+
- **Configuration Loader (clippy_config)**: \`Conf::read\` parses \`clippy.toml\`, inline attributes (\`#[allow(clippy::lint)]\`), CLI overrides; influences lint levels and params.
28+
- **Lint Utilities (clippy_utils)**: Reusable functions for lints (e.g., type queries, def path matching, expression analysis).
29+
- **Rustc Infrastructure**: \`rustc_driver\`, \`rustc_interface\`, \`rustc_session\` for session management, diagnostics; \`rustc_lint\` for pass registration.
30+
- **Development Helpers**: Tracks files/envs for incremental builds; ICE hook for bug reporting to GitHub.
31+
32+
## Main Execution Flow
33+
34+
The primary sequence illustrates invocation, mode decision, and compiler orchestration.
35+
36+
```mermaid
37+
sequenceDiagram
38+
participant U as User
39+
participant D as clippy-driver
40+
participant RD as rustc_driver
41+
participant C as Compiler Config & Callbacks
42+
participant LS as Lint Store
43+
participant CP as Compilation Pipeline
44+
participant L as Lint Passes
45+
46+
U->>D: Invoke with args (e.g., file.rs [options])
47+
D->>D: Parse args, handle --help/--version/--rustc
48+
alt Clippy enabled (no cap-lints=allow, etc.)
49+
D->>D: Add --cfg clippy, CLIPPY_ARGS
50+
D->>RD: run_compiler(args, ClippyCallbacks)
51+
RD->>C: config() - load conf, set opts (mir_opt_level=0)
52+
C->>LS: register_lint_passes() - add early/late lints
53+
RD->>C: psess_created() - track deps (Cargo.toml, etc.)
54+
RD->>CP: Run phases (parse, expand, typeck, MIR, ...)
55+
loop During phases
56+
CP->>L: Execute registered passes (EarlyLintPass, LateLintPass, ...)
57+
L->>CP: Emit diagnostics if issues found
58+
end
59+
else Rustc mode
60+
D->>RD: run_compiler(args, RustcCallbacks)
61+
RD->>CP: Standard compilation without Clippy lints
62+
end
63+
CP->>D: Output diagnostics, artifacts
64+
D->>U: Print to stdout/stderr, exit code
65+
```
66+
67+
## Lint Registration and Execution Flow
68+
69+
Clippy registers passes tailored to compiler phases; execution occurs interleaved with compilation.
70+
71+
### Registration Details
72+
- **Deprecated Handling**: Registers renames/removals for backward compatibility.
73+
- **Early Passes**: ~50+ implementations for syntax/style checks (e.g., \`DoubleParens\`, \`Formatting\`).
74+
- **Late Passes**: ~300+ for semantic analysis (e.g., \`Types\`, \`Methods\`, \`Loops\`), using \`TyCtxt\` for context.
75+
- **Shared State**: Some passes share storage (e.g., \`FormatArgsStorage\`) across lints.
76+
77+
### Execution Sequence
78+
```mermaid
79+
sequenceDiagram
80+
participant P as Compilation Pipeline
81+
participant LS as Lint Store
82+
participant EP as Early Passes
83+
participant LP as Late Passes
84+
85+
Note over P: Parsing & Expansion Phase
86+
P->>LS: Run pre-expansion passes
87+
LS->>EP: Execute EarlyLintPass (e.g., Attributes)
88+
EP->>P: Potential diagnostics
89+
90+
Note over P: Post-Expansion (AST/HIR)
91+
P->>LS: Run early passes
92+
LS->>EP: EarlyLintPass (e.g., formatting, doc checks)
93+
EP->>P: Emit diagnostics
94+
95+
Note over P: Type Checking & MIR
96+
P->>LS: Run late passes
97+
LS->>LP: LateLintPass with TyCtxt (e.g., types, methods, loops)
98+
LP->>P: Emit diagnostics via session
99+
```
100+
101+
## Other Relevant High-Level Design Aspects
102+
103+
- **Performance Considerations**: MIR opt level set to 0 avoids optimizations that could obscure bugs (e.g., constant folding); disables specific passes like \`CheckNull\`. Trade-off: Slower compilation for accuracy.
104+
- **Incremental Compilation**: Tracks runtime-accessed files (Cargo.toml, clippy.toml, driver exe) in \`file_depinfo\` and envs (CLIPPY_CONF_DIR, CLIPPY_ARGS) for Cargo-triggered rebuilds.
105+
- **Configuration Flexibility**: Hierarchical (CLI > file > attributes); supports lint groups, custom params (e.g., max nesting depth).
106+
- **Fallback and Compatibility**: Supports plain rustc delegation for queries or suppressed lints; handles arg files (\`@path\`), sysroot env.
107+
- **Extensibility**: Lints implement traits like \`EarlyLintPass\` or \`LateLintPass\`; new ones added via dev tools, auto-registered in \`lib.rs\`.
108+
- **Diagnostics**: Leverages rustc's system for structured output (spans, suggestions via rustfix); colorized via anstream.
109+
- **Limitations**: Tied to rustc version (via \`rustc_private\`); requires nightly for dev; no built-in fix mode (use cargo clippy --fix).
110+
- **Testing Integration**: Used in UI tests, dogfooding; ensures lints trigger correctly in direct mode.
111+
112+
This design draws from source analysis of \`src/driver.rs\`, \`clippy_lints/src/lib.rs\`, and cross-references with project architecture in \`project-overview.md\`. For implementation details, see relevant crates' READMEs and Rustc driver docs.

0 commit comments

Comments
 (0)