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

Feature request: custom library-specific lints #6872

Open
alice-i-cecile opened this issue Mar 9, 2021 · 13 comments
Open

Feature request: custom library-specific lints #6872

alice-i-cecile opened this issue Mar 9, 2021 · 13 comments
Labels
S-needs-discussion Status: Needs further discussion before merging or work can be started

Comments

@alice-i-cecile
Copy link

Over at Bevy we've been discussing building a linter for Bevy code bases, to catch common errors and style issues.

We'd love to be able to integrate with Clippy in some way, but obviously, almost all of these will be completely useless to Rustaceans who aren't using Bevy. Furthermore, we'd want to maintain our own lints, without bogging down the rust-clippy team directly.

What would be the best way to go about this?

@llogiq
Copy link
Contributor

llogiq commented Mar 9, 2021

I had a discussion with the maintainer of shipyard, who asked if we could somehow change the too_many_arguments lint to avoid systems. In general we have no qualms about crate specific lints (see e.g. the regex lints).

If it helps you to get up to speed, you might want to start lints in our nursery and later move them to another project if you deem that the best course of action.

Also perhaps some of the lints you want may be generalizable. What is it that you want to have linted?

@bjorn3
Copy link
Member

bjorn3 commented Mar 9, 2021

From bevyengine/bevy#1602:

  • malformed systems (see ty::TyTuple fields mismatch #1519)
  • unit structs in the first type parameter of Query (these should just use With)
  • using Not<With> or Not<Without> or the like

These are highly specific lints to bevy for which generalization doesn't make any sense.

@llogiq
Copy link
Contributor

llogiq commented Mar 9, 2021

  • Looking around, I see that shipyard has a system! macro; this would be a good entry point to implement custom warnings / errors. How would we detect malformed systems and how should the warning message look?
  • The "unit struct in first type of Query" as well as the "Not<With(out)>"should be simple enough to detect and we should be able to reuse the logic for other lints that forbid specific type combinations. We already have lints that check type sizes, and lints that check for certain types.

@bjorn3
Copy link
Member

bjorn3 commented Mar 9, 2021

Bevy uses it's own ECS. Systems are ordinary functions on which .system() from the IntoSystem trait is called. This would be a good entry point for Bevy.

@Michael-J-Ward
Copy link

A second use case that I just asked about on tracing discord would be a lint to warns you whenever a task is spawned without being instrumented.

@alice-i-cecile
Copy link
Author

I've been pointed to this issue, asking about a replacement for now deprecated functionality that seems like it would have met our goals: Alternatives to rustc_plugin::registry for (Servo’s) custom lints?.

@spacejam
Copy link

spacejam commented Mar 11, 2021

I have a list of Rust features that I usually consider inappropriate to use in my projects due to compile time/correctness/usability hazards, but probably would be viewed as overly conservative by most clippy users. I would love to be able to ban various things using a custom lint such as:

  • pub trait
  • proc macro use
  • pub macro
  • internal async usage
  • unused derive impl on non-pub type
  • Drop implemented
  • threads spawned dynamically

I've recently come across the Ravenscar ADA Profile which grants significant safety properties to concurrent hard real-time systems, and I've really been jealous about how that community is able to opt into a restricted feature set to significantly reduce the cost of building safer systems.

@llogiq
Copy link
Contributor

llogiq commented Mar 12, 2021

Most of those seem easy to implement and all of the fit nicely into our restriction lint category. The "threads spawned dynamically" lint would be quite hard, because we only perform local analysis and threads could be spawned in functions from other crates. However, we could still lint calls to std::thread::spawn if that helps. Same goes for "internal async usage"; this can be done locally, but not transitively in all dependencies.

@shepmaster
Copy link
Member

shepmaster commented Jul 16, 2021

I'd love to be able to create some lints for non-ideal usages of SNAFU!

we have no qualms about crate specific lints

It certainly seems odd to have those be a part of Clippy proper — will people really be happy with increased Clippy build times / size / code complexity for a crate they might never use?

I also wonder about how versioning would work: if Regex substantially changed its API, would Clippy be able to know which version(s) were in play and offer appropriate suggestions?

I guess I was thinking of some wild process where Clippy dlopens a shared library that exports some data structures (I suppose like dylint or something like inventory. Then people could have something in their Cargo.toml that lets Clippy know of these:

[package.metadata.clippy]
plugin = ["snafu-clippy"]

@abonander
Copy link

I recently posted a proposal for proc-macro based lints: https://internals.rust-lang.org/t/proposal-stabilizable-proc-macro-based-lints/15022/19

@jhpratt
Copy link
Member

jhpratt commented Jul 19, 2021

@shepmaster is already aware of this, but I plan on writing up some of my thoughts for a plugin-based lint system. I'll probably start doing this Tuesday evening and hope to have something to post on Wednesday on IRLO. It'll be a lot of work but long-term I think it will be worth it. @flip1995 has also expressed interest in helping out in this manner.

@giraffate giraffate added the S-needs-discussion Status: Needs further discussion before merging or work can be started label Oct 5, 2021
@xmo-odoo
Copy link

xmo-odoo commented Apr 12, 2022

I also wonder about how versioning would work: if Regex substantially changed its API, would Clippy be able to know which version(s) were in play and offer appropriate suggestions?

Definitely a non-trivial issue, but also something which seems like it would be extremely valuable to libraries for exactly these situations: per the rustfix readme,

The magic of rustfix is entirely dependent on the diagnostics implemented in the Rust compiler (and external lints, like clippy).

I interpret this as meaning that clippy support would be necessary for libraries to be able to use rustfix for their API changes. Such a thing would make iterating on 0.x a lot easier, especially if a library gains significantly in popularity before it reaches 1.0: while 0.x is for development, having tons of users makes BC breaks more wasteful even while you're supposedly allowed to.

@xFrednet
Copy link
Member

Hey everyone, in response to this, a new project was set up to implement a general stable linting interface for Rust. As part of the designing process, I would like to collect some user stories. If you have the time, it would be appreciated if you could create an issue detailing your custom lint idea: https://github.com/rust-linting/design/issues/new?assignees=&labels=A-user-story&template=user-story.md

This can be in the form of a short and simple list (like this), or a detailed lint with example code (like this). With these user stories, I'm especially interested in the role of macros when it comes to linting. Any feedback is highly appreciated :)

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