Rust

Rust Code Review with LGTM

AI code review for Rust: LGTM catches lifetime annotation issues, unnecessary unsafe blocks, missed `?` short-circuits, Arc/Rc misuse, and panics in library code — beyond what the borrow checker flags.

How LGTM reviews Rust PRs

Tree-sitter's Rust grammar handles Rust's full syntax cleanly — macros, lifetimes, trait bounds, async, const generics. Our indexer extracts fn, struct, enum, trait, impl, mod, and pub-use re-exports across the crate.

The Rust compiler already catches a huge class of bugs. LGTM's value is in the layer ABOVE: design choices, API ergonomics, panic safety, async correctness, and the patterns that compile fine but bite at runtime.

Per-PR: 5-15 most-related symbols pulled by PageRank, attached to agent prompts. The Bugs agent for Rust focuses on patterns rustc + clippy don't fully cover: panic in library code, blocking I/O in async functions, Arc cycles, channel misuse, lock ordering.

Common Rust patterns LGTM flags

Unnecessary `unsafe`. The Security agent flags `unsafe { ... }` blocks that don't actually need unsafety (e.g., wrapping a pointer cast that has a safe equivalent). Each finding suggests the safe alternative.

Panic in library code. `unwrap()`, `expect()`, indexing, integer overflow in -O3 — flagged in code that's marked as library (no main function, lib.rs entry). Application code gets more leniency.

Missed `?` short-circuit. `let x = result.map_err(|e| { ... })?` chains that could be simpler. Style finding, low confidence — surfaced in summary not inline.

Arc/Rc misuse. Arc inside single-threaded async — should be Rc. Rc shared across threads — won't compile but the design pattern that led there is flagged. Arc cycles (rare but real) caught by reading the type graph.

Blocking calls in async functions. `std::fs::read_to_string(path)` inside `async fn` — blocks the tokio runtime. The Performance agent flags every std::fs / std::thread::sleep / std::net call inside async contexts.

Channel deadlocks. `let (tx, rx) = channel(); ... rx.recv().unwrap();` where tx isn't closed. The agent reads the send/recv pattern and flags suspicious cases.

Tree-sitter coverage for Rust

Mature tree-sitter Rust grammar. All major Rust 2018/2021/2024 edition syntax parses cleanly. Macros are parsed at the token level (tree-sitter doesn't expand them) — meaning we see the macro invocation but not what it expands to. This is fine for most review purposes; the macro definition itself is reviewable.

Cargo workspace support: every Cargo.toml at the workspace root or in members is read. Cross-crate references resolve correctly.

Trait impls and associated functions are extracted as symbols. `impl Display for Foo` registers as both a Foo-related symbol and a Display-related cross-reference.

Setup notes for Rust projects

Install the LGTM GitHub App. Index time: 30-90 seconds for typical Rust services, 2-5 minutes for large workspaces with many crates.

Cargo.lock is NOT used by LGTM directly — we don't fetch crates or build. Only Cargo.toml is read for workspace/member resolution.

Build artifacts (target/) are excluded by default. Generated code (build.rs output, prost-build .pb.rs) is auto-excluded by `OUT_DIR` heuristics.

BYOK keys work the same as other languages. Rust code's lower verbosity often means smaller diffs and lower token cost per review — typical 300-line Rust PR is ~$0.04-$0.10 on GPT-4o.

Example bugs LGTM catches

Blocking call in async function
// ❌ Bug: blocks the tokio runtime
async fn load_config(path: &Path) -> Result<Config> {
    let text = std::fs::read_to_string(path)?;  // <-- blocking!
    Ok(serde_json::from_str(&text)?)
}

// LGTM finding:
// "std::fs::read_to_string blocks; calling it inside async fn
//  blocks the runtime's executor thread. Use tokio::fs::read_to_string
//  or wrap in tokio::task::spawn_blocking."
Unwrap in library code
// ❌ Pattern: panics on bad caller input
pub fn parse_port(s: &str) -> u16 {
    s.parse().unwrap()    // panics on non-numeric input
}

// LGTM finding:
// "Library function panics on caller-controlled input.
//  Return Result<u16, ParsePortError> so callers can recover.
//  Public API should not panic on bad input."

See LGTM reviewing Rust

tree-sitter Rust · workspace-aware · unsafe-focused agent

Go to the product page

Rust review FAQs

Does LGTM run cargo check / clippy?

No — pure static analysis via tree-sitter + LLM. Run clippy in your CI; LGTM catches the patterns clippy can't articulate as lint rules.

Macro-heavy crates support?

Tree-sitter parses macro invocations at the token level — we see the call site but not the expansion. For most review purposes (catching design issues, suspicious patterns) this is fine. Macros that expand to control flow are still readable as long as you can read their invocation.

no_std support?

Yes. The agents recognise no_std contexts (lib.rs with #![no_std]) and avoid suggesting std-dependent fixes.

async-trait / GATs?

Parse correctly. The Best-Practices agent recognises async-trait usage and surfaces modern alternatives when applicable.

What about FFI and bindings crates?

extern "C" blocks parse fine. The agents are extra cautious on FFI boundaries — the Security agent flags unsafe-FFI patterns more aggressively because the cost of a bug there is high.

Related across LGTM

Other languages