|
| 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