You have to for resilient macro_rules! macros as well, because item names are resolved at the call site. Example:
macro_rules! m {
() => {Vec::<u8>::new()};
}
mod ok {
fn f() {
m!();
}
}
mod nok {
type Vec = u8;
fn f() {
m!(); // ~ Error: no function or associated item named `new` found for type `u8`
}
}
This is not a great argument. Someone still has to write the macro, and that someone has to maintain the code the macro outputs. It's much easier to do so the less namespace noise that is present.
A "perfect"ly implemented macro_rules! macro that wanted to use the std's Vec would use $crate::_reexports::alloc::vec::Vec. A more prepared one night use $crate::_reexports::Vec, if they make their hidden _reexports module directly reƫxport the types they are using.
A less paranoid macro would just use ::alloc::vec::Vec, or maybe ::std::vec::Vec. (If you're using std, there's no reason for your downstream to be #![no_std], and renaming not-std to be used at ::std is just asking for things to not work.)
The "proper" solution for the macro (decl or proc) is full def-site hygeine for all items, not just local bindings ("macros 2.0"). But reƫxporting items at their shortest reasonable path would be an improvement for macros in the short term, where full hygeine is decidedly long-term.
Adding a marker trait like Unpin to the prelude is specifically not a breaking change because it doesn't contain any new associated items like methods, which could conflict with the items of other traits the user has already brought into scope and cause a compile failure in existing code.
But that is easily solvable by IDE, at least by Intlij Rust plugin, just hit Alt+Enter and it generates use. I'm not sure if it works with Rust Analyzer.
I haven't used IntelliJ Rust in a little while, but other IntelliJ products have Ctrl+Alt+O (Optimize Imports) which can automatically remove unused imports.
Indeed. I haven't used hotkey, but manual way on unused imports with a tooltip. But my point was that when you experiment with code, you comment some lines out, then uncomment and import is useful again. It's a bit of annoyance.
And if you have this situation a lot, and want to silence the warnings, you can also temporarily add #[allow(unused)] or #[allow(unused_imports)] to the module you're working on.
I think I feel differently depending on how big and complicated the work to integrate into a editor it is. I agree you shouldn't need some nontrivial-startup-time IDE like Eclipse or VS. But where's that line? I generally don't consider Sublime Text to be "an IDE", but it can still give me buttons to apply structured suggestions from rust(c|ls|a|whatever). And that's a huge help that I would encourage everyone to setup. Note that even the playground has click-to-add-use.
Overall, though, I feel like if the problem is the uses, then changing use std::time::Instant; to use std::Instant; doesn't really move the needle to me. Similarly for the non-use version of std::time::Instant::now() vs std::Instant::now().
Everything in the root also feels like it's just asking for more use std::*;, too -- which C++ learned (from using namespace std; is not a good thing.
I think the answer here is prelude(s), not reexporting in the root of crates.
While I also think that use * is usually wrong, I don't think this particular argument is applicable in Rust. using namespace std; is problematic in C++ primarily because of C++ specific concerns, like dumping symbols into the global namespace (especially if done in header files) or adding a lot of overload resolutions. Start imports are much less problematic (and idiomatic) in Kotlin&Java.
To be clear, I don't have a position I want to argue for in this discussion, I just want to nitpick sightly flawed reasoning