Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lint for preventing unwanted module uses #885

Closed
regexident opened this issue Apr 27, 2016 · 2 comments
Closed

Lint for preventing unwanted module uses #885

regexident opened this issue Apr 27, 2016 · 2 comments
Labels
S-needs-discussion Status: Needs further discussion before merging or work can be started

Comments

@regexident
Copy link

regexident commented Apr 27, 2016

One of my more ambitious projects (~20 traits, ~50 impls of said traits) aims to be fully modular, extensible and generic.

As such the project's overall module structure looks something like this:

├── dolor
│   ├── amet
│   │   ├── adipiscing.rs
│   │   ├── consectetur.rs
│   │   ├── elit.rs
│   │   └── mod.rs
│   ├── mod.rs
│   └── sit.rs
├── ipsum.rs
├── lib.rs
└── lorem
    └── mod.rs

With the mod.rs usually containing a specific abstract traits and its accompaning Rust files containing concrete impls.

From time to time I catch myself erroneously and thoughtlessly adding a use statement for a concrete impl to one of those mod.rs files, which results in a module dependency coupling that I want to avoid at all costs.

As such I'd love to be able to add an attribute to my conrete impl modules prohibiting the use by their abstract trait (super) module.

/dolor/mod.rs:

trait Dolor { ... }

/dolor/amet.rs:

use dolor;

trait Amet: Dolor { ... }

/dolor/amet/elit.rs:

// either by relative path:
#![deny(use_by(super::super, super))]
// or by absolute path:
#![deny(use_by(dolor, dolor::amet))]

use dolor::{self, amet};

struct AmetImpl { ... }

impl Dolor for AmetImpl { ... }

impl Amet for AmetImpl { ... }

/dolor/amet/adipiscing.rs:

... // basically no #![deny(use_by(...))]

So if I was to change /dolor/mod.rs to this:

use amet::elit;
use amet::adipiscing;

trait Dolor { ... }

I should get a clippy error:

use amet::elit; // ERROR: prohibited use of `amet::elit`.

Now in reality things tend to be a bit more complex.
Thus it would have to be able to resolve indirect used and flag those, too.

As such changing /dolor/amet/adipiscing.rs to this…

use super::elit;

...

… should now produce two clippy errors in /dolor/mod.rs:

use amet::elit; // ERROR: prohibited direct use of `amet::elit`!
use amet::adipiscing; // ERROR: prohibited indirect use of `amet::elit`!

This is probably possible even with vanilla clippy.
But using @llogiq's metacollect it would probably be a piece of cake even.

@Manishearth
Copy link
Member

This doesn't need metacollect since I think attributes are stored in the def map. However, this seems like a very specific use case, perhaps more suited for a separate lint crate?

@oli-obk oli-obk added the S-needs-discussion Status: Needs further discussion before merging or work can be started label May 10, 2017
@camsteffen
Copy link
Contributor

This is solved by pub(restricted) since Rust 1.18.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-needs-discussion Status: Needs further discussion before merging or work can be started
Projects
None yet
Development

No branches or pull requests

4 participants