Description
Code
use crate::*;
use std::alloc::*;
use std::any::*;
use std::array::*;
use std::fmt::*;
use std::fs::*;
use std::io::*;
use std::iter::*;
use std::num::*;
use std::ops::*;
use std::sync::atomic::*;
use std::sync::*;
Desired output
warning: it's time to stop
--> /my/rust/module/with/too/many/globs.rs:LL:CC
|
LL | use crate::*;
| ^^^^^^^^
= note: using items introduced by this glob becomes ambiguous if upstream adds something using that name
|
LL | use std::alloc::*;
| ^^^^^^^^^^^^^
= note: globbing from your own crate and then from an upstream crate is a bad idea!
= help: actually name the items you want to use? please?
except maybe less sassy.
Rationale and extra context
If you glob import from an upstream crate once, it's okay. If you glob import from multiple local modules, that's probably okay if they all have non-glob imports. If you glob import from different modules in an upstream crate multiple times, or an upstream crate and then a local crate, you are running a very high risk of breaking yourself.
This is basically "how could we have avoided getting into this case?" for a regression on the current beta: #142427
I think that this is different from the clippy::wildcard_imports
lint. That clippy lint fires on basically any glob imports outside of a few special cases. Here we want to be smarter and identify when it poses a serious risk for upstream additions. In particular, we want to make it easier for std
to add new types and traits when it deems necessary without worrying too much about conflicts, so we could even choose to implement this lint only for globs from std
.
We might also have special cases (e.g. we may have to specially handle the preludes in some way) but we could allow basically any one glob always, and any combination of globs that have contents entirely subject to local control. This would let people actually use them where they are appropriate. There are also globs which are in-principle a closed set and we could give a pass, like enums (unless they are #[non_exhaustive]
), as globbing an enum is a common pattern.
The main risk, I think, aside from the usual social ones, would be that completely precise "are these transitive globs all local?" analysis may prove pretty challenging, so we may be better off accepting the occasional false positive. One saving grace is that the analysis only requires proving that we've globbed an upstream and a local crate, as we're not actually concerned whether the current compilation works out and are instead warning for semver reasons.
Rust Version
rustc 1.89.0-nightly (6ccd44760 2025-06-08)
binary: rustc
commit-hash: 6ccd4476036edfce364e6271f9e190ec7a2a1ff5
commit-date: 2025-06-08
host: x86_64-unknown-linux-gnu
release: 1.89.0-nightly
LLVM version: 20.1.5
Anything else?
No response