{"id":50988380,"url":"https://github.com/estebank/redpen","last_synced_at":"2026-07-07T22:00:30.667Z","repository":{"id":191975681,"uuid":"686107284","full_name":"estebank/redpen","owner":"estebank","description":"A Rust code linter","archived":false,"fork":false,"pushed_at":"2024-06-10T20:11:18.000Z","size":213,"stargazers_count":213,"open_issues_count":5,"forks_count":4,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-05-26T18:11:02.861Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/estebank.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-01T19:03:12.000Z","updated_at":"2026-02-17T12:47:00.000Z","dependencies_parsed_at":"2024-05-23T00:44:42.527Z","dependency_job_id":"56828396-fbed-42fa-930e-c9cb7ec95a71","html_url":"https://github.com/estebank/redpen","commit_stats":null,"previous_names":["estebank/redpen"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/estebank/redpen","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/estebank%2Fredpen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/estebank%2Fredpen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/estebank%2Fredpen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/estebank%2Fredpen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/estebank","download_url":"https://codeload.github.com/estebank/redpen/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/estebank%2Fredpen/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35243953,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-07T02:00:07.222Z","response_time":90,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-19T23:00:38.172Z","updated_at":"2026-07-07T22:00:30.648Z","avatar_url":"https://github.com/estebank.png","language":"Rust","funding_links":[],"categories":["Linters"],"sub_categories":[],"readme":"# Red Pen ️❌🖊\n\n`redpen` is a linter for Rust code.\n\n## Goals\n\nThe aim of this tool is to:\n\n* have its own custom sets of lints independent of clippy to allow for different defaults\n* work as a test bed for internal `rustc` API stabilization\n* act as a buffer between lints written for this tool and that internal API by providing its own API for compiler internals so that changing `rustc` API internals don't require regularly rewriting lints (this work has not yet been started)\n* be quick to compile as part of CI so that projects can write project specific lints\n\n## Implemented lints\n\nCurrently, only two lints have been written\n\n - a simple lint that operates as a \"negative trait check\", that complains if a type parameter of an annotated type is used with a specific type\n - a much more useful assertion that the annotated fn will not transitively call panic\n\n## Meaning of the name\n\nThe tool is named after the writing instrument a teacher would use to mark mistakes in your paper. [`rustc` is a strict teacher][teacher]. `redpen` is a *very* strict teacher.\n\n[teacher]: https://twitter.com/ekuber/status/1438178928984829959\n\n## Installation and usage\n\nThere are two ways of using this tool. If you are only interested in using existing lints, you can install through `cargo` with `cargo +nightly-2024-05-06 install redpen-linter`. After that you can invoke `redpen` as if you were invoking `cargo check`. You must ensure that the appropriate Rust 1.72 compiler is installed with `rustup toolchain add nightly-2024-05-06`, as `redpen` is tightly coupled with a specific compiler version's internal APIs. Additionally, you must also add the following to your `Cargo.toml` in the `[dependencies]` section:\n\n```\n[dependencies]\ncargo-redpen-shim = { version = \"0.1\", package = \"redpen\" }\n```\n\nThis is necessary so that when running regular `cargo` commands, like `cargo build`, the custom linting annotations will be picked up as valid item attributes and not fail your build.\n\nIf you want to keep your own set of lints, then you'll have to keep your own working copy of the different `redpen` components.\n\nClone this repository and run `cargo install`:\n\n```console\nexport LD_LIBRARY_PATH=$(rustup run nightly-2024-05-06 bash -c \"echo \\$LD_LIBRARY_PATH\")\ngit clone https://github.com/estebank/redpen.git\ncd redpen\ncargo install --path .\n```\n\nNote that `redpen` is pinned to a Rust version so it is likely that running `cargo install --git` will not work as it will not use the `rust-toolchain` file in the repository.\n\nIf you're adding new lints, you will also want to provide your own `redpen` proc-macro crate.\n\n## What it looks like\n\nGiven a `src/main.rs` with the following contents:\n\n```rust\n#[redpen::disallow(T = \"Pineapple\")]\nstruct Pizza\u003cT\u003e(T);\n\nstruct Pineapple;\n\n#[allow(dead_code)]\ntype Alias = Pizza\u003cPineapple\u003e;\n\nimpl Pineapple {\n    fn foo(\u0026self) {\n        panic!(\"foo\");\n    }\n}\n\n#[redpen::dont_panic]\nfn bar() {\n    Pineapple.foo();\n    let mut v = vec![1];\n    v.swap_remove(0);\n    v[1];\n    panic!(\"asdf\");\n}\n\nfn main() {\n    bar();\n    let _ = Pizza(Pineapple);\n}\n```\n\nExecuting `redpen` will produce the following output:\n\n```\n$ redpen\n   Compiling pizza v0.1.0 (/home/gh-estebank/pizza)\nerror: `bar` can panic\n  --\u003e src/main.rs:16:1\n   |\n15 | #[redpen::dont_panic]\n   | --------------------- the function can't panic due to this annotation\n16 | fn bar() {\n   | ^^^^^^^^ this function can panic\n17 |     Pineapple.foo();\n   |               --- panic can occur here\n18 |     let mut v = vec![1];\n19 |     v.swap_remove(0);\n   |       ----------- panic can occur here\n20 |     v[1];\n   |     ---- panic can occur here\n21 |     panic!(\"asdf\");\n   |     -------------- panic can occur here\n   |\n   = note: `#[deny(redpen::dont_panic)]` on by default\n\nerror: type parameter `T` in `Pizza` can't be `Pineapple`\n --\u003e src/main.rs:7:20\n  |\n7 | type Alias = Pizza\u003cPineapple\u003e;\n  |                    ^^^^^^^^^\n  |\n  = note: `#[deny(redpen::disallow)]` on by default\n\nerror: type parameter `T` in `Pizza` can't be `Pineapple`\n  --\u003e src/main.rs:26:13\n   |\n26 |     let _ = Pizza(Pineapple);\n   |             ^^^^^^^^^^^^^^^^ this expression is of type `Pizza\u003cPineapple\u003e`\n\n    Finished dev [unoptimized + debuginfo] target(s) in 0.02s\n```\n\n## How it works\n\nThis linter is implemented as a `rustc_driver`, effectively a different entry point to the regular `rustc` implementation. It links against the pre-built `rustc_*` components, so you're only compiling a very small amount of code, keeping its builds quite fast.\n\n`redpen_wrapper` is a very small CLI tool that is meant to act as a passthrough between `cargo` and `rustc`. It is invoked through `RUST_WRAPPER=redpen_wrapper cargo build`. This allows us to use `rustc` to build a given crate, and only once this is done, execute `redpen` to execute the lints and collect metadata necessary for cross-crate analysis (like the `panic!()` reachability lint).\n\n`cargo-redpen` is a small CLI that invokes `cargo build` with the appropriate environement variables. It executes:\n\n```console\nexport LD_LIBRARY_PATH=$(rustup run nightly-2024-05-06 bash -c \"echo \\$LD_LIBRARY_PATH\")\n\nRUSTC_WRAPPER=$PATH_TO/redpen_wrapper \\\nRUSTC_BOOTSTRAP=1 \\\ncargo +nightly-2024-05-06 build \\\n-Zbuild-std \\\n--target x86_64-unknown-linux-gnu # haven't tried in other platforms, experiment replacing this for your case\n```\n\n## Ancestry notice\n\nThis linter was initially based of off [the Rust-on-Linux linter klint][klint], which in turn leverages the `rustc` codebase.\n\n[klint]: https://github.com/Rust-for-Linux/klint\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Festebank%2Fredpen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Festebank%2Fredpen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Festebank%2Fredpen/lists"}