After my earlier proposal I had the idea that instead of a complete overhaul of semantics, there might be a solution in small, individual changes.
So with the recent discussions and pain points that have been brought up, I have reduced the proposal to two features and an inaction.
I should again point out that all of the ideas are taken from earlier proposals.
#![feature(structured_paths)]
Instead of the current path formats, the following will be recognized:
-
foo::bar
(starting with an identifier) is relative to the current module. -
::foo::bar
(starting with::
) is an absolute path in the current crate (see Options below for an alternative). -
extern::cratename::foo
(starting withextern::
) is absolute in another crate. -
super::foo
andself::foo
as relative prefixes are as they are today.
The extern::
path is regarded as external crate reference, meaning there
is no need to use extern crate
for it to work. However, the external
crate is only available through extern::
and not as an item in
the current crate root.
This feature is not backwards compatible. It would require a feature flag or an epoch-like facility to activate by default.
Options
-
::foo::bar
could becrate::foo::bar
, but that is bikeshedding territory as they both would have the same semantics. -
extern::cratename::
could have different syntax, which would also not change the semantics and is more a visual discussion.
#![feature(glob_modules)]
Keep mod
working just the way it is currently, but allow the module
name to be replaced with *
causing all submodules of the current
module to be loaded, except those loaded explicitly. Renaming is
disallowed (for now) with the glob variant.
As an example, assuming the following files:
src/lib.rs
src/a.rs
src/b.rs
src/c/mod.rs
src/c/lower.rs
then the following statement at the crate root src/lib.rs
:
pub(crate) mod *;
pub mod a;
will expand to:
pub(crate) mod b;
pub(crate) mod c;
pub mod a;
Note that it only pulls in direct submodules of the current module, and does not affect any lower submodules.
The rationale for requiring *
for mod when extern crate
is no
longer necessary is that extern::
paths don’t introduce items in the
module tree, but mod
does. The *
is semantically symmetric to the one
in a glob import use foo::*
. Both mark sources of items pulled in the
current namespace that aren’t explicitly mentioned.
This feature is backwards compatible and can be enabled by default.
The extern crate
situation.
The structured_paths
feature above means there is no need for an
explicit extern crate foo
if the path extern::foo
is accessed
anywhere.
However, I would propose to leave the extern crate
as it is right
now and not deprecate it because:
- It can still be used to import a crate root as an item into the current module.
- Having it only be an import of a crate root is backwards compatible.
- Existing documentation and examples continue to work in providing
a local symbol where
extern crate
is used. - It doesn’t have to be deprecated now and a separate discussion can be had if it should get hard-removed in future epochs, or linted, or kept.
Edit: Added extern::cratename::
to Options as visual discussion topic and fixed some prose. Adjusted extern crate
section to mention possible future deprecation. Thanks to @RalfJung!