Skip to content

rust@v1

Hygiene checks for Rust projects. Adopt it with:

extends:
- alint://bundled/rust@v1

This ruleset is gated with when: facts.has_rust (true if any Cargo.toml exists anywhere in the tree) plus a per-rule scope_filter: { has_ancestor: Cargo.toml } on per-file content rules so they only apply to files inside a Rust package — useful in polyglot monorepos where Rust packages sit alongside Node / Python / Go subdirectories. Rules that don’t apply stay quiet. (has_rust is declared below; override with your own facts: block if you need a different heuristic.)

Rust project: Cargo.toml at the repo root is required.

Committing Cargo.lock ensures reproducible builds for binary crates. Library-only workspaces may legitimately opt out; set this rule’s level: off in that case.

Pinning a toolchain (rust-toolchain.toml) makes local and CI builds reproducible.

  • kind: dir_absent
  • level: error
  • when: facts.has_rust

target/ is Cargo’s build dir and must never be committed.

Rust module filenames must be snake_case.

Trojan Source (CVE-2021-42574): bidi override chars in Rust sources are rejected.

Zero-width characters in Rust sources are rejected (review hazard).

The full ruleset definition is committed at crates/alint-dsl/rulesets/v1/rust.yml in the alint repo (the snapshot below is generated verbatim from that file).

# alint://bundled/rust@v1
#
# Hygiene checks for Rust projects. Adopt it with:
#
# extends:
# - alint://bundled/rust@v1
#
# This ruleset is gated with `when: facts.has_rust` (true if any
# `Cargo.toml` exists anywhere in the tree) plus a per-rule
# `scope_filter: { has_ancestor: Cargo.toml }` on per-file content
# rules so they only apply to files inside a Rust package — useful
# in polyglot monorepos where Rust packages sit alongside
# Node / Python / Go subdirectories. Rules that don't apply stay
# quiet. (`has_rust` is declared below; override with your own
# `facts:` block if you need a different heuristic.)
version: 1
facts:
- id: has_rust
any_file_exists: [Cargo.toml, "**/Cargo.toml"]
rules:
# --- Workspace / package manifest ---------------------------------
- id: rust-cargo-toml-exists
when: facts.has_rust
kind: file_exists
paths: Cargo.toml
root_only: true
level: error
message: "Rust project: Cargo.toml at the repo root is required."
- id: rust-cargo-lock-exists
when: facts.has_rust
kind: file_exists
paths: Cargo.lock
root_only: true
level: warning
message: >-
Committing Cargo.lock ensures reproducible builds for binary
crates. Library-only workspaces may legitimately opt out; set
this rule's `level: off` in that case.
policy_url: "https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html"
- id: rust-toolchain-pinned
when: facts.has_rust
kind: file_exists
paths: ["rust-toolchain.toml", "rust-toolchain"]
root_only: true
level: info
message: "Pinning a toolchain (rust-toolchain.toml) makes local and CI builds reproducible."
# --- Build artefacts must not be tracked --------------------------
- id: rust-no-tracked-target
when: facts.has_rust
kind: dir_absent
paths: "**/target"
level: error
message: "`target/` is Cargo's build dir and must never be committed."
# --- Source-file conventions --------------------------------------
# v0.9.18: default-exclude subtrees with deliberately non-snake-case
# filenames. Three categories surface in rust-lang/rust:
#
# src/doc/** — doc examples + reference snippets
# use English-style hyphenation
# (`rustc-driver-example.rs`,
# `rust-by-example/...`).
# src/tools/miri/tests/** — Miri test fixtures use CamelCase /
# intentional naming for litmus tests
# and concurrency-spec semantics
# (`abi_mismatch_repr_C.rs`,
# `libc_pthread_mutex_NULL_reentrant.rs`).
# src/tools/clippy/tests/ui/** — clippy UI test fixtures use
# curly braces, hyphens, and other
# non-snake-case markers as part of
# the test grammar.
# **/*.miri.rs — `.miri.rs` dot-suffix is a Miri-only
# override file pattern; the dot in
# the basename trips snake-case.
#
# Without these excludes, rust-lang/rust alone surfaced 1,091
# false positives — the largest single bundled-rule FP class in
# the case-study corpus. The excludes are unique to rust-lang/rust
# + similar compiler/test-fixture projects; they're a no-op for
# most repos.
- id: rust-sources-snake-case
when: facts.has_rust
kind: filename_case
paths:
include: ["**/src/**/*.rs"]
exclude:
- "src/doc/**"
- "src/tools/miri/tests/**"
- "src/tools/clippy/tests/ui/**"
- "src/tools/rustfmt/tests/**"
- "tests/rustdoc-gui/**"
- "**/*.miri.rs"
case: snake
level: error
message: "Rust module filenames must be snake_case."
fix:
file_rename: {}
- id: rust-sources-final-newline
when: facts.has_rust
kind: final_newline
paths: "**/*.rs"
scope_filter:
has_ancestor: Cargo.toml
level: warning
fix:
file_append_final_newline: {}
- id: rust-sources-no-trailing-whitespace
when: facts.has_rust
kind: no_trailing_whitespace
paths: "**/*.rs"
scope_filter:
has_ancestor: Cargo.toml
level: info
fix:
file_trim_trailing_whitespace: {}
# --- Trojan Source defense on Rust sources ------------------------
- id: rust-sources-no-bidi
when: facts.has_rust
kind: no_bidi_controls
paths: "**/*.rs"
scope_filter:
has_ancestor: Cargo.toml
level: error
message: "Trojan Source (CVE-2021-42574): bidi override chars in Rust sources are rejected."
policy_url: "https://trojansource.codes/"
- id: rust-sources-no-zero-width
when: facts.has_rust
kind: no_zero_width_chars
paths: "**/*.rs"
scope_filter:
has_ancestor: Cargo.toml
level: error
message: "Zero-width characters in Rust sources are rejected (review hazard)."
# --- Workspace-level niceties -------------------------------------
- id: rust-no-merge-markers-in-manifests
when: facts.has_rust
kind: no_merge_conflict_markers
paths: ["Cargo.toml", "**/Cargo.toml", "Cargo.lock", "**/Cargo.lock"]
scope_filter:
has_ancestor: Cargo.toml
level: error