rust-clippy
rust-clippy copied to clipboard
Lint to catch 'overlapping' wildcard globs
What it does
By default in rust when using wildcards in use
statements, and two modules export things with overlapping names then rather than throw an error, the compiler just uses the first and 'silently' ignores the others.
Example:
lib.rs
mod test1;
mod test2;
pub use test1::*;
pub use test2::*;
test1.rs
enum MyEnum {
Item1,
Item2,
}
test2.rs
enum MyEnum {
Item1,
Item2,
Item3,
}
Now we probably can't put this in the compiler as it is a breaking change, however a clippy lint for this would be nice. For context I am working with generated code and have only recently noticed that part of the api is not exported (and therefor broken) due to this issue.
https://github.com/arlyon/async-stripe/issues/66
I suggest a lint that detects overlapping wildcards and exposes a warning to the user on the imports that suffer from this issue about what is going on.
Categories (optional)
- Kind: clippy::suspicious
What is the advantage of the recommended code over the original code
This will help detect subtle issues that can arise from 'import erasure' (for lack of a better term).
Drawbacks
None.
Example
warning: this wildcard exports test2::MyEnum which clashes with test1::MyEnum causing it to be ignored
--> src/lib.rs:5:1
|
5 | pub use test2::*;
| ^^^^^^^^^^^^^^^^^ help: consider changing the names to prevent a clash or importing explicitly
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#overlapping_wildcards
This would be useful, but should handle any case where the glob overlaps with something, regardless of if the 2nd thing itself also came from a glob.
That is, from your example: if you move the contents of one of the modules directly into lib.rs
, I think the lint should still trigger — only one of the things needs to be from a glob.
Concretely, I had this situation happen recently, which unintentionally tries to export two different crate::bar
modules, but only exports one, silently hiding the other.
mod foo {
pub mod bar;
}
pub use foo::*;
pub mod bar;
FWIW, I was looking into what it would take to implement this, and discovered that two cases are actually now implemented as compiler-builtin lints:
- Ambiguous glob re-exports (https://github.com/rust-lang/rust/pull/107880) as of rustc 1.70.0
- Shadowing re-exports with a private item (https://github.com/rust-lang/rust/pull/111378) as of rustc 1.72.0
I think those could probably be expanded to include the third case mentioned here... I haven't read all the discussion from those PRs but if these lints were accepted to the upstream compiler it might make sense to just add more cases there rather than a clippy lint.
Yeah, happy to close this clippy-side!