This likely arises when one’s mental model is“making a file makes a module”, and hence you expect to be able to use items from files in your project without any ceremony.
Similarly, adding a dependency to Cargo.toml can feel like the dep has … been added! And therefore that you should be able to use from it straightaway.
Conclusion: a world in which you use use to bring things into scope, full stop, seems like a big improvement.
Confusion around absolute vs relative paths
A contributing factor is surely that, when you have a submodule, you can immediately refer to it within signatures and expressions. It’s then jarring that if you want to explicitly use items from within that module, you need self::
It’s not really the case that signatures/expressions use“relative” paths. Rather, they use what’s in scope. But submodules are always in scope.
OTOH, requiring you to use a submodule to be able to name it seems unergonomic…
Choice of absolute paths for use
A big part of the argument was that absolute paths are the common case.(See also the same story in Python)
However, this is likely due to the large number of imports from other crates, especially std, and it’s confusing that those are“mounted at root” anyway.
You could imagine instead doing:
use vec from std, i.e. where the thing after from is always a crate
This clears up confusion around the root namespace
It also gives you more clarity about what is coming from this crate versus external crates
However: still need a story for ::std::vec::Vec::new() in expressions etc.
Maybe leading :: is repurposed to mean“crate” and can be followed by either external crate names, or crate to jump to root of the current crate?
Is it feasible to just deprecate this syntax?
use foo could then be relative(backcompat concerns…)
Would probably still want use super:: to be a thing?
Could have use top_level_mod from crate or some such as a way to jump to root
This opens the door to pub use for exporting submodules
Wasn’t a great option before due to needing pub use self::
What would this mean for pub(restricted), which rightfully uses absolute paths?
Confusion/annoyance with mod.rs
Just allow foo/ and foo.rs to coexist
Eventually deprecate mod.rs
There’s a possible back-compat story here:
Introduce and stabilize use from
Deprecate use without leading self or super, instead pushing usage to use from
This can be done with rustfmt! Super easy to automate.
use HashMap from std::collections;use collections::HashMap from std;use {self, Read, Write} from std::io;
use my_sub_module::Foo;use Foo from my_sub_module;
// shorthand:use foo;// for:use foo from self;
use Foo from self::my_sub_module;use my_sub_module::Foo;