Skip to content

Rules

Forty-six rules across five families. Every one can be disabled, reweighted, or given a different severity in configuration.

Rules are namespaced by their category, so doc addresses the whole family and doc/work-marker addresses one rule.

rust

Idiomaticity, error handling, and abstractions with no second user.

RuleSeverityDefaultWhat it reports
rust/unwrap-in-libraryhighonA fallible value is unwrapped outside tests, so the failure path is unhandled
rust/panic-in-libraryhighonLibrary code panics instead of returning an error
rust/expect-in-librarymediumonA fallible value is resolved with expect outside tests
rust/panicking-indexmediumonIndexing can panic on out-of-range input
rust/single-implementor-traitmediumonA crate-private trait has one implementor, so the indirection has no second user
rust/oversized-functionmediumonA function body is longer than the configured maximum
rust/deep-nestingmediumonA block is nested more deeply than the configured maximum
rust/single-use-wrapperlowonA wrapper type only forwards to its inner value
rust/over-exposed-visibilitylowonAn item is public but referenced only within its own module
rust/manual-index-looplowonA range loop only indexes a collection, where an iterator would read more clearly
rust/match-on-boollowonA match on a boolean where a conditional would read more clearly
rust/needless-returnlowonAn explicit return at the end of a function body
rust/oversized-filelowonA file is longer than the configured maximum
rust/single-instantiation-genericlowoffA generic parameter is instantiated at exactly one type
rust/single-caller-indirectionlowoffA function exists solely to forward to another and has one caller

Error-handling rules are exempt in test code, whether that is an inline #[cfg(test)] module, an integration test target, or a file reached only through a test-only module declaration.

typescript

What a declaration earns its keep doing, and what discards the checking around it.

RuleSeverityDefaultWhat it reports
typescript/cast-through-unknownhighonA cast passes through unknown to reach an unrelated type, defeating the check a single cast would have had
typescript/single-implementor-interfacemediumonAn unexported interface has one implementor, so the indirection has no second user
typescript/explicit-anymediumonA position is written as any, discarding the checking the rest of the file relies on
typescript/non-null-assertionmediumonAn expression asserts a value is present rather than establishing it
typescript/unexplained-suppressionmediumonA suppression comment carries no reason for suppressing anything
typescript/aliasing-typelowonA type alias renames a single named type without adding meaning
typescript/optional-heavy-typelowonMost of a type's properties are optional, so it states little about its values
typescript/barrel-modulelowonA module only forwards names declared elsewhere
typescript/duplicate-shapelowonTwo declarations describe the same shape under different names
typescript/console-in-librarylowonLibrary code writes to the console, which its callers did not ask for
typescript/default-exportlowonA module exports a value whose name every importing site chooses for itself

.d.ts files are not analyzed. A declaration file states an interface without implementing it and is usually written by tsc, so the rules about implementors, forwarding, and console calls have nothing to read. node_modules is never walked, whether or not the project ignores it.

Six of these are also linter rules

explicit-any, non-null-assertion, unexplained-suppression, console-in-library and default-export have equivalents in Biome or typescript-eslint. cast-through-unknown has none.

They ship because TypeScript linting is opted into twice, by installing a tool and by turning the individual rule on. A project with no configuration is not one that decided these were acceptable; it is one where nothing is checking them. That differs from Rust, where clippy comes with the toolchain, and where rules duplicating it were removed during calibration.

Each therefore asks first whether the project already enforces it:

What the project hasWhat the rule does
biome.json or .eslintrc.json enabling the equivalent, directly or through a presetstays silent
No linter configuration at allreports, confirmed
Configuration only as JavaScript, such as a flat eslint.config.tsreports, unconfirmed

Configuration is read as data and never executed, for the same reason the analyzer never builds the project it is pointed at.

c

What a declaration does with the reach it is given.

RuleSeverityDefaultWhat it reports
c/missing-internal-linkagemediumonA function is exposed to the whole program while only its own file uses it
c/definition-in-headermediumonA header carries a function body, so every including file gets a copy
c/orphan-declarationmediumonA header declares a function no analyzed file defines
c/file-scope-mutable-statemediumonMutable state at file scope is readable and writable from every file in the program
c/unincluded-headerlowonAn interface file states an interface no analyzed file includes

.c and .h are both read as C. A header written for C++ produces a parse diagnostic naming the file rather than being silently reported as understood.

Nothing is preprocessed

No macro is expanded, no include resolved, and no condition evaluated, even where the definition needed sits in the analyzed tree. Expanding a macro means resolving include paths and evaluating conditionals, which is running the build.

The cost is measured and large. Across twenty widely deployed C projects, 97.6 percent of c findings came back unconfirmed and nineteen of the twenty carried no score, because every one of them invokes macros at file scope. Read C findings individually; do not expect a c score. See calibration.

doc

Whether the prose informs anyone.

RuleSeverityDefaultWhat it reports
doc/missing-on-public-itemmediumonA public item carries no documentation
doc/documented-parameter-absentmediumonDocumentation describes a parameter the signature does not declare
doc/commented-out-codemediumonCommented-out source was left in place
doc/restates-signaturelowonDocumentation adds nothing beyond the item name and signature
doc/undocumented-parameterlowonA parameter is undocumented while its siblings are documented
doc/restating-commentlowonA comment paraphrases the statement below it
doc/work-markerlowonAn unresolved work marker was left in source
doc/unresolved-referencemediumoffDocumentation links to an identifier that does not resolve
doc/contentless-bannerlowoffA banner or separator comment carries no content

"Public" means reachable from outside the crate, not merely written pub. An item inside a private module, or one marked #[doc(hidden)], is not part of the documented API and is left alone.

A comment above an unsafe operation is exempt from restating-comment: that is where the reasoning making the operation sound gets written. Code introduced by prose ending in a colon is read as illustration rather than as leftovers.

filler

Volume without meaning. Every rule here is low severity by default, because each pattern has legitimate uses.

RuleSeverityDefaultWhat it reports
filler/narrating-commentslowonMost statements in a function carry a comment restating them
filler/defensive-redundancylowonA check cannot fail given a guarantee already established
filler/templated-documentationlowonMany items share one documentation template with only the name substituted
filler/repeated-wrapperlowonStructurally identical wrappers repeat across a module
filler/unimplemented-markerlowonA non-test function body consists only of an unimplemented marker
filler/simplification-disclaimerlowonProse states that the surrounding code is simplified or not production ready

Nothing in this family makes any claim about who or what wrote the code. It describes patterns, and a test asserts that no message, category name, or serialized field expresses an opinion about authorship.

Rules that ship switched off

Four rules are disabled by default because measurement showed them reporting their own imprecision rather than sloppiness. Each carries its reason in the catalog, and calibration has the numbers.

Turn any of them on for a run:

sh
slopometer . --enable doc/contentless-banner

Or in configuration:

toml
[rules."doc/contentless-banner"]
enabled = true

Dual licensed under MIT or Apache-2.0.