- Feature Name: from_crate_use_item
- Start Date: 2017-08-05
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)
Summary
One source of confusion identified in learning Rust is the extern crate
statement
and its relation to use
and mod
statements. Part of this confusion is the fact
that extern crate
introduces the external crate as an item in the root of the
current crate, which while being consistent, is hard to reason about when learning
and hard to teach. This RFC attempts to introduce a replacement syntax which
combines the functionality of extern crate
and use
statements into a single
from <crate> use <item>
syntax, with a superset of the current functionality.
Motivation
The primary motivation is to reduce confusion between extern crate
and use
,
while unifying on syntax which is looks like use
and is somewhat familiar with
other languages.
Guide-level explanation
The following example:
from crate_name use item_name;
Can be viewed as doing the same thing as:
extern crate crate_name;
use crate_name::item_name;
With a single exception, which is that crate_name
is not introduced as an item
and it is not placed in the current scope. This allows using items from external
crates without the names of those crates polluting the current crates namespace
unnecessarily. Only used items need to be brought into scope.
Note, it is never possible to have an absolute path in a statement, e.g.
from foo use ::bar;
This is invalid because ::bar
refers to the current crate, not an item within foo
.
This means that this proposal fits well with teaching both current use
and a
proposed use
which prefers relative over absolute paths.
Reference-level explanation
There are a few forms of extern crate
which need to be accounted for in order
to provide a complete solution, so that extern crate
might be deprecated.
extern crate foo;
from foo use self;
extern crate "invalid-identifier" as valid_identifier;
from "invalid-identifier" use self as valid_identifier;
The following sugar could be added to allow for more compact use of the statement:
from foo use {
x::y,
a::{b, c},
}
This would be equivalent to:
from foo use x::y;
from foo use a::{b, c};
This new syntax may be used wherever use
statements may currently be used.
The design is such that an automated tool could convert every extern crate
statement into the appropriate from <crate> use self
statement which is
equivalent as part of the new epoch proposal.
I believe that from would work as a contextual keyword for this design, given that it only requires two token lookahead to check for the existence of use, which is a keyword.
Note, to reexport a symbol, the syntax is from <crate> pub use <item>;
.
Drawbacks
- The
from <crate> use self as alternate_name;
syntax is probably more confusing than the current syntax. However, this is unlikely to ever be used by a human and it is the obvious way to create a superset of the current functionality in order to allow automated upgrades of older codebases to the newer syntax. - The complexity of this addition to the language may not provide enough benefit to be worth doing.
Rationale and Alternatives
- This design is focused on unifying
extern crate
anduse
through the addition of a targeted feature, which is backwards compatible. Most other designs which accomplish the same thing, are either proposals which include this functionality as a subset or propose a solution which removes functionality in an attempt to simplify. - Alternate designs:
- The impact of not doing this is likely more user confusion about
extern crate
anduse
. - One alternative would be to introduce a new name lookup syntax which allows specifying
a crate, like
@crate_name::item_name
, such thatuse @crate_name::item_name;
would be the same asfrom crate_name use item_name;
. Whether the@
sigil would be used or a different syntax is currently an open question. Iād prefer to not increase the scope of this proposal to include changes to name lookup outsideuse
-like statements. A concern is that introducing changes to name lookup may make it less familiar to current Rust developers and given how little documentation there is on name lookup currently, it seems best to not increase complexity in this area.
Unresolved questions
- Should it be
from foo pub use bar;
orpub use bar from foo;
? I currently preferfrom foo pub use bar;
, mostly because I think the crate name is important, though usually short and the multi-import syntax works better with the crate at the beginning.