Propagate individual items (but not glob imports) for use throughout the crate

I was thinking that it would be nice if we could make items propagate throughout the crate to avoid some of the use boilerplate that is often needed. When I searched the forum, I came across this fairly recent post, which suggested allowing custom prelude imports, and linked to this (fairly old) RFC where that had been suggested previously.

At first glance, I really liked the idea, but as I read other people's comments in the RFC, I think they had some valid concerns that this could be (ab)used in a way that essentially creates a private Rust dialect, making the resulting code much harder to read and possibly harder to write as well.

This is due to the drawbacks mentioned in the forum post referenced above:

As I was thinking about that, I thought of a similar idea which would technically would still have two of the same drawbacks, but might be harder to abuse.

The main issue with the prelude suggestion, as I see it, is the ability, with a one-line use statement, to propagate into the entire crate an arbitrary number of symbols which are hidden away in some other crate. And, taking it a step further, this could be done for a whole ecosystem of crates with a single line in the root of each crate.

So, my thought was, what if we only allow symbols to propagate if they are explicitly mentioned in the root of the crate, essentially not allowing glob imports to be propagated.

For example:

// within lib.rs

// changed the name of the attribute from previously made
// suggestions since we aren't propagating an entire prelude.
#![propagate]
use std::rc::Rc; // `Rc` no longer needs a `use` in sub-modules

// none of these will need `use` in sub-modules
#![propagate]
use some_other_crate::prelude::{
    SomeTrait as _,
    SomeStruct,
    SomeOtherStruct as AnotherName,
    some_macro,
};

// #![propagate]
// use std::io::prelude::*; // ERROR: cannot propagate glob imports

// the above erroneous `use` could be replaced with the
// following (or leave out any that are not needed
#![propagate]
use std::io::{
    BufRead,
    Read,
    Seek,
    Write,
};

This has the advantage that every propagated symbol is mentioned in the root of the crate so it's easy to find. And because of the work involved people will most likely do one of the following:

  • Only propagate the symbols they really need (ideal); or
  • Create a template with tons of imports that they use as the starting point for every crate in their larger project, company or group (perhaps not ideal, but at least the symbols are fairly easy to find, improving code readability over the prelude propagation suggestions)

Note that I do appreciate glob prelude imports at the module level as they exist now, but I see where propagating those throughout one or more crates could really hurt readability.