Compile check: the code behind the articles
Every Rust example from the articles, and exactly what the Rust 1.99 compiler and Clippy said about them.
Two articles on this site make claims about code that compiles cleanly:
- Why learn Rust when an AI can write it? says that four common patterns in AI-written Rust compile without a murmur, and that
cargo clippywith its default settings says nothing about them either. - Reviewing AI-written Rust: six things to check says the same of its “before” examples, and that its “after” examples compile and pass their tests.
This page is the evidence: the code, the toolchain, and the output of every command. It was checked on 12 October 2026 with Rust 1.99.0.
The page is generated by a small Rust tool in the site’s repository. When the site is released, the tool rebuilds the examples, fails if any claim on this page no longer holds, and rewrites the page. It also checks that every Rust snippet in the articles is part of the code it compiles. A weekly job runs the same checks against the latest stable Rust.
The output is unedited, except that the temporary directory the crate is built in is shown as /tmp/article-examples.
The code
One library crate, with a module for each article.
Cargo.toml:
[package]
name = "article-examples"
version = "0.1.0"
edition = "2024"
publish = false
[dependencies]clippy.toml lets tests use unwrap() and expect() when the opt-in lints that forbid them elsewhere are switched on, as the reviewing article suggests. It has no effect on Clippy’s default lints.
allow-unwrap-in-tests = true
allow-expect-in-tests = truesrc/lib.rs:
//! The Rust examples from the articles on rust-primer.org, gathered into one
//! crate so that the claims the articles make about them can be checked.
pub mod reviewing;
pub mod why_learn;src/why_learn.rs, the four patterns from the first article:
//! The four patterns from "Why learn Rust when an AI can write it?", written
//! the way an assistant typically produces them.
use std::sync::{Arc, Mutex};
/// 1. A function that clones a vector because borrowing it was awkward.
pub fn count_long(names: Vec<String>) -> usize {
names.iter().filter(|name| name.len() > 5).count()
}
pub fn report_long_names(names: Vec<String>) -> String {
// The caller still needs `names` afterwards, so the move is "fixed" with a clone.
let long = count_long(names.clone());
format!("{long} of {} names are long", names.len())
}
/// 2. A parser that calls unwrap() and takes the whole process down on bad input.
pub fn parse_port(input: &str) -> u16 {
input.trim().parse().unwrap()
}
/// 3. A library that reports every failure as a String.
pub fn parse_config_line(line: &str) -> Result<(String, u16), String> {
let (key, value) = line
.split_once('=')
.ok_or_else(|| format!("missing '=' in {line:?}"))?;
let port = value
.trim()
.parse()
.map_err(|e| format!("bad port {value:?}: {e}"))?;
Ok((key.trim().to_string(), port))
}
/// 4. Shared state wrapped in Arc<Mutex<_>> in code that never leaves one thread.
pub fn word_count(text: &str) -> usize {
let count = Arc::new(Mutex::new(0));
for _word in text.split_whitespace() {
*count.lock().unwrap() += 1;
}
*count.lock().unwrap()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_patterns_behave_as_described() {
let names = vec!["Ada".to_string(), "Grace Hopper".to_string()];
assert_eq!(report_long_names(names), "1 of 2 names are long");
assert_eq!(parse_port(" 8080 "), 8080);
assert!(std::panic::catch_unwind(|| parse_port("http")).is_err());
let (key, port) = parse_config_line("web = 80").expect("a valid line");
assert_eq!((key.as_str(), port), ("web", 80));
assert!(
parse_config_line("web")
.unwrap_err()
.contains("missing '='")
);
assert_eq!(word_count(" a b c\n"), 3);
}
}src/reviewing.rs, the “before” and “after” examples from the reviewing article:
//! The examples from "Reviewing AI-written Rust: six things to check".
/// The "before" examples: what an assistant typically writes.
pub mod before {
use std::sync::{Arc, Mutex};
pub fn count_long(names: Vec<String>) -> usize {
names.iter().filter(|name| name.len() > 5).count()
}
pub fn print_long_names() -> usize {
let names = vec!["Ada".to_string(), "Grace Hopper".to_string()];
let long = count_long(names.clone());
println!("{long} of {} names are long", names.len());
long
}
pub fn parse_port(input: &str) -> u16 {
input.trim().parse().unwrap()
}
#[derive(Debug, Clone, PartialEq)]
pub struct User {
pub id: u32,
pub name: String,
}
pub fn find_user(users: &[User], id: u32) -> Option<User> {
users.iter().find(|user| user.id == id).cloned()
}
pub fn word_count(text: &str) -> usize {
let count = Arc::new(Mutex::new(0));
for _word in text.split_whitespace() {
*count.lock().unwrap() += 1;
}
*count.lock().unwrap()
}
}
/// The "errors as strings" example, which has no direct "after" version.
pub mod strings {
pub fn parse_port(input: &str) -> Result<u16, String> {
input
.trim()
.parse()
.map_err(|e| format!("bad port {input:?}: {e}"))
}
}
/// The "after" examples: what to ask for instead.
pub mod after {
use std::num::ParseIntError;
#[derive(Debug, PartialEq, Eq)]
pub enum PortError {
NotANumber(ParseIntError),
Zero,
}
pub fn parse_port(input: &str) -> Result<u16, PortError> {
match input.trim().parse() {
Ok(0) => Err(PortError::Zero),
Ok(port) => Ok(port),
Err(e) => Err(PortError::NotANumber(e)),
}
}
pub fn count_long(names: &[String]) -> usize {
names.iter().filter(|name| name.len() > 5).count()
}
pub fn print_long_names() -> usize {
let names = vec!["Ada".to_string(), "Grace Hopper".to_string()];
let long = count_long(&names);
println!("{long} of {} names are long", names.len());
long
}
#[derive(Debug, PartialEq)]
pub struct User {
pub id: u32,
pub name: String,
}
pub fn find_user(users: &[User], id: u32) -> Option<&User> {
users.iter().find(|user| user.id == id)
}
pub fn word_count(text: &str) -> usize {
text.split_whitespace().count()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_port() {
assert_eq!(parse_port("8080"), Ok(8080));
}
#[test]
fn trims_surrounding_whitespace() {
assert_eq!(parse_port(" 443\n"), Ok(443));
}
#[test]
fn rejects_port_zero() {
assert_eq!(parse_port("0"), Err(PortError::Zero));
}
#[test]
fn rejects_empty_and_out_of_range_input() {
assert!(matches!(parse_port(""), Err(PortError::NotANumber(_))));
assert!(matches!(parse_port("65536"), Err(PortError::NotANumber(_))));
assert!(matches!(parse_port("-1"), Err(PortError::NotANumber(_))));
}
#[test]
fn finds_a_user_by_reference() {
let users = vec![User {
id: 1,
name: "Ada".into(),
}];
assert_eq!(
find_user(&users, 1).map(|user| user.name.as_str()),
Some("Ada")
);
assert_eq!(find_user(&users, 2), None);
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn before_and_after_agree_where_the_input_is_valid() {
assert_eq!(
super::before::print_long_names(),
super::after::print_long_names()
);
assert_eq!(super::before::parse_port("8080"), 8080);
assert_eq!(super::strings::parse_port("8080"), Ok(8080));
assert_eq!(
super::before::word_count(" a b c\n"),
super::after::word_count(" a b c\n")
);
let users = vec![super::before::User {
id: 1,
name: "Ada".into(),
}];
assert_eq!(
super::before::find_user(&users, 1).map(|user| user.name),
Some("Ada".to_string())
);
}
#[test]
fn before_parse_port_panics_on_bad_input() {
assert!(std::panic::catch_unwind(|| super::before::parse_port("http")).is_err());
}
#[test]
fn strings_parse_port_reports_a_message() {
let error = super::strings::parse_port("http").expect_err("not a number");
assert!(error.starts_with("bad port \"http\""));
}
}The toolchain
$ rustc --version
rustc 1.99.0 (b940084d7 2026-09-28)
$ cargo --version
cargo 1.99.0 (5f94df478 2026-08-27)
$ cargo clippy --version
clippy 0.1.99 (b940084d7e 2026-09-28)rustc
Compiling the crate directly with rustc printed nothing at all and exited with status 0, which means no warnings and no errors.
$ rustc --edition 2024 --crate-type lib --out-dir target src/lib.rsCargo
The same result through Cargo, building the library and its tests from clean:
$ cargo build --all-targets
Compiling article-examples v0.1.0 (/tmp/article-examples)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.50sClippy, default lints
$ cargo clippy --all-targets
Checking article-examples v0.1.0 (/tmp/article-examples)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.22sTests
The tests check that each example behaves as the articles describe, including the unwrap() parsers panicking on "http" and the “after” port parser rejecting 0, 65536 and -1.
$ cargo test
Compiling article-examples v0.1.0 (/tmp/article-examples)
Finished `test` profile [unoptimized + debuginfo] target(s) in 0.57s
Running unittests src/lib.rs (target/debug/deps/article_examples-331a8af81a4f29e7)
running 9 tests
test reviewing::after::tests::finds_a_user_by_reference ... ok
test reviewing::after::tests::parses_port ... ok
test reviewing::after::tests::rejects_empty_and_out_of_range_input ... ok
test reviewing::after::tests::rejects_port_zero ... ok
test reviewing::after::tests::trims_surrounding_whitespace ... ok
test reviewing::tests::before_and_after_agree_where_the_input_is_valid ... ok
test reviewing::tests::strings_parse_port_reports_a_message ... ok
test reviewing::tests::before_parse_port_panics_on_bad_input ... ok
test why_learn::tests::the_patterns_behave_as_described ... ok
test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Doc-tests article_examples
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00sWhat this shows, and what it does not
It shows that, with Rust 1.99.0 and edition 2024, none of these examples produces a warning from the compiler or from Clippy’s default lints, and that the tests pass.
It does not mean the patterns go unnoticed by every tool. With the whole pedantic group and the unwrap_used and expect_used lints switched on, Clippy flags two of them:
clippy::needless_pass_by_value, in thepedanticgroup, flags the functions that take aVec<String>they only read:count_longandreport_long_namesin the first article’s code, and the “before”count_longin the reviewing article’s.clippy::unwrap_used, in therestrictiongroup, flags theunwrap()calls inparse_portandword_count, both in the first article’s code and in the reviewing article’s “before” examples.
Nothing in those lints objects to the String errors, to returning a cloned User, or to the unnecessary Arc<Mutex<_>>. pedantic also asks for # Errors and # Panics sections and #[must_use] attributes, which are documentation points rather than design ones. The remaining patterns still need a person who understands why they are a problem. Later versions of Rust and Clippy may add warnings for some of them, which is why the articles say “at the time of writing”.