6.1 KiB
- Start Date: 2014-07-16
- RFC PR #: #169
- Rust Issue #: https://github.com/rust-lang/rust/issues/16461
Summary
Change the rebinding syntax from use ID = PATH
to use PATH as ID
,
so that paths all line up on the left side, and imported identifiers
are all on the right side. Also modify extern crate
syntax
analogously, for consistency.
Motivation
Currently, the view items at the start of a module look something like this:
mod old_code {
use a::b::c::d::www;
use a::b::c::e::xxx;
use yyy = a::b::yummy;
use a::b::c::g::zzz;
}
This means that if you want to see what identifiers have been
imported, your eyes need to scan back and forth on both the left-hand
side (immediately beside the use
) and the right-hand side (at the
end of each line). In particular, note that yummy
is not in scope
within the body of old_code
This RFC proposes changing the grammar of Rust so that the example above would look like this:
mod new_code {
use a::b::c::d::www;
use a::b::c::e::xxx;
use a::b::yummy as yyy;
use a::b::c::g::zzz;
}
There are two benefits we can see by comparing mod old_code
and mod new_code
:
-
As alluded to above, now all of the imported identifiers are on the right-hand side of the block of view items.
-
Additionally, the left-hand side looks much more regular, since one sees the straight lines of
a::b::
characters all the way down, which makes the actual differences between the different paths more visually apparent.
Detailed design
Currently, the grammar for use statements is something like:
use_decl : "pub" ? "use" [ ident '=' path
| path_glob ] ;
Likewise, the grammar for extern crate declarations is something like:
extern_crate_decl : "extern" "crate" ident [ '(' link_attrs ')' ] ? [ '=' string_lit ] ? ;
This RFC proposes changing the grammar for use statements to something like:
use_decl : "pub" ? "use" [ path "as" ident
| path_glob ] ;
and the grammar for extern crate declarations to something like:
extern_crate_decl : "extern" "crate" [ string_lit "as" ] ? ident [ '(' link_attrs ')' ] ? ;
Both use
and pub use
forms are changed to use path as ident
instead of ident = path
. The form use path as ident
has the same
constraints and meaning that use ident = path
has today.
Nothing about path globs is changed; the view items that use
ident = path
are disjoint from the view items that use path globs,
and that continues to be the case under path as ident
.
The old syntaxes
"use" ident '=' path
and
"extern" "crate" ident '=' string_lit
are removed (or at least deprecated).
Drawbacks
-
pub use export = import_path
may be preferred overpub use import_path as export
since people are used to seeing the name exported by apub
item on the left-hand side of an=
sign. (See "Have distinct rebinding syntaxes foruse
andpub use
" below.) -
The 'as' keyword is not currently used for any binding form in Rust. Adopting this RFC would change that precedent. (See "Change the signaling token" below.)
Alternatives
Keep things as they are
This just has the drawbacks outlined in the motivation: the left-hand side of the view items are less regular, and one needs to scan both the left- and right-hand sides to see all the imported identifiers.
Change the signaling token
Go ahead with switch, so imported identifier is on the left-hand side,
but use a different token than as
to signal a rebinding.
For example, we could use @
, as an analogy with its use as a binding
operator in match expressions:
mod new_code {
use a::b::c::d::www;
use a::b::c::e::xxx;
use a::b::yummy @ yyy;
use a::b::c::g::zzz;
}
(I do not object to path @ ident
, though I find it somehow more
"line-noisy" than as
in this context.)
Or, we could use =
:
mod new_code {
use a::b::c::d::www;
use a::b::c::e::xxx;
use a::b::yummy = yyy;
use a::b::c::g::zzz;
}
(I do object to path = ident
, since typically when =
is used to
bind, the identifier being bound occurs on the left-hand side.)
Or, we could use :
, by (weak) analogy with struct pattern syntax:
mod new_code {
use a::b::c::d::www;
use a::b::c::e::xxx;
use a::b::yummy : yyy;
use a::b::c::g::zzz;
}
(I cannot figure out if this is genius or madness. Probably madness,
especially if one is allowed to omit the whitespace around the :
)
Have distinct rebinding syntaxes for use
and pub use
If people really like having ident = path
for pub use
, by the
reasoning presented above that people are used to seeing the name
exported by a pub
item on the left-hand side of an =
sign, then we
could support that by continuing to support pub use ident = path
.
If we were to go down that route, I would prefer to have distinct notions of the exported name and imported name, so that:
pub use a = foo::bar;
would actually import bar
(and a
would
just be visible as an export), and then one could rebind for export
and import simultaneously, like so:
pub use exported_bar = foo::bar as imported_bar;
But really, is pub use foo::bar as a
all that bad?
Allow extern crate ident as ident
As written, this RFC allows for two variants of extern_crate_decl
:
extern crate old_name;
extern crate "old_name" as new_name;
These are just analogous to the current options that use =
instead of as
.
However, the RFC comment dialogue suggested also allowing a renaming form that does not use a string literal:
extern crate old_name as new_name;
I have no opinion on whether this should be added or not. Arguably
this choice is orthogonal to the goals of this RFC (since, if this is a
good idea, it could just as well be implemented with the =
syntax).
Perhaps it should just be filed as a separate RFC on its own.
Unresolved questions
- In the revised
extern crate
form, is it best to put thelink_attrs
after the identifier, as written above? Or would it be better for them to come after thestring_literal
when using theextern crate string_literal as ident
form?