Open
Description
What it does
Forbids mutually recursive module dependencies within a crate.
Consider two modules, crate::foo
and crate::bar
. If foo
uses bar
, then bar
must not use foo
(and vice versa). At a high level, this enforces that the crate's internal dependency tree forms a DAG.
Categories (optional)
- Kind: probably pedantic
What benefit of this lint over old code?
- Keep a crate's internal dependency tree manageable
- This helps in understanding the structure of an unfamiliar codebase
- This can aid future refactors of a monolithic crate into smaller crates
- Possibly speed up compilation by making it easier for rustc to internally parallelize builds of a single crate or divide a crate into isolated codegen units for incremental compilation
I stole the idea from tending, originally posted here. Further discussion in that thread
Prior art: eslint import/no-cycle
Drawbacks
Possibly too pedantic for some projects
Example
foo.rs
use crate::bar::bar;
struct Common {}
pub fn foo(common: &Common) {
bar(common);
}
bar.rs
use crate::foo::Common;
pub fn bar(common: &Common) {}
Could be written as:
common.rs
struct Common {}
foo.rs
use crate::common::Common;
use crate::bar::bar;
pub fn foo(common: &Common) {
bar(common);
}
bar.rs
use crate::common::Common;
pub fn bar(common: &Common) {}