|
| 1 | +- Feature Name: use_nested_groups |
| 2 | +- Start Date: 2017-08-25 |
| 3 | +- RFC PR: https://github.com/rust-lang/rfcs/pull/2128 |
| 4 | +- Rust Issue: https://github.com/rust-lang/rust/issues/44494 |
| 5 | + |
| 6 | +# Summary |
| 7 | +[summary]: #summary |
| 8 | + |
| 9 | +Permit nested `{}` groups in imports. |
| 10 | +Permit `*` in `{}` groups in imports. |
| 11 | + |
| 12 | +```rust |
| 13 | +use syntax::{ |
| 14 | + tokenstream::TokenTree, // >1 segments |
| 15 | + ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}, // nested braces |
| 16 | + ext::build::AstBuilder, |
| 17 | + ext::quote::rt::Span, |
| 18 | +}; |
| 19 | + |
| 20 | +use syntax::ast::{self, *}; // * in braces |
| 21 | + |
| 22 | +use rustc::mir::{*, transform::{MirPass, MirSource}}; // both * and nested braces |
| 23 | +``` |
| 24 | + |
| 25 | +# Motivation |
| 26 | +[motivation]: #motivation |
| 27 | + |
| 28 | +The motivation is ergonomics. |
| 29 | +Prefixes are often shared among imports, especially if many imports |
| 30 | +import names from the same crate. With this nested grouping it's more often |
| 31 | +possible to merge common import prefixes and write them once instead of writing |
| 32 | +them multiple times. |
| 33 | + |
| 34 | +# Guide-level explanation |
| 35 | +[guide-level-explanation]: #guide-level-explanation |
| 36 | + |
| 37 | +Several `use` items with common prefix can be merged into one `use` item, |
| 38 | +in which the prefix is written once and all the suffixes are listed inside |
| 39 | +curly braces `{}`. |
| 40 | +All kinds of suffixes can be listed inside curly braces, including globs `*` and |
| 41 | +"subtrees" with their own curly braces. |
| 42 | + |
| 43 | +```rust |
| 44 | +// BEFORE |
| 45 | +use syntax::tokenstream::TokenTree; |
| 46 | +use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; |
| 47 | +use syntax::ext::build::AstBuilder, |
| 48 | +use syntax::ext::quote::rt::Span, |
| 49 | + |
| 50 | +use syntax::ast; |
| 51 | +use syntax::ast::*; |
| 52 | + |
| 53 | +use rustc::mir::*; |
| 54 | +use rustc::mir::transform::{MirPass, MirSource}; |
| 55 | + |
| 56 | +// AFTER |
| 57 | +use syntax::{ |
| 58 | + // paths with >1 segments are permitted inside braces |
| 59 | + tokenstream::TokenTree, |
| 60 | + // nested braces are permitted as well |
| 61 | + ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}, |
| 62 | + ext::build::AstBuilder, |
| 63 | + ext::quote::rt::Span, |
| 64 | +}; |
| 65 | + |
| 66 | +// `*` can be listed in braces too |
| 67 | +use syntax::ast::{self, *}; |
| 68 | + |
| 69 | +// both `*` and nested braces |
| 70 | +use rustc::mir::{*, transform::{MirPass, MirSource}}; |
| 71 | + |
| 72 | +// the prefix can be empty |
| 73 | +use { |
| 74 | + syntax::ast::*; |
| 75 | + rustc::mir::*; |
| 76 | +}; |
| 77 | + |
| 78 | +// `pub` imports can use this syntax as well |
| 79 | +pub use self::Visibility::{self, Public, Inherited}; |
| 80 | +``` |
| 81 | + |
| 82 | +A `use` item with merged prefixes behaves identically to several `use` items |
| 83 | +with all the prefixes "unmerged". |
| 84 | + |
| 85 | +# Reference-level explanation |
| 86 | +[reference-level-explanation]: #reference-level-explanation |
| 87 | + |
| 88 | +Syntax: |
| 89 | +``` |
| 90 | +IMPORT = ATTRS VISIBILITY `use` [`::`] IMPORT_TREE `;` |
| 91 | +
|
| 92 | +IMPORT_TREE = `*` | |
| 93 | + REL_MOD_PATH `::` `*` | |
| 94 | + `{` IMPORT_TREE_LIST `}` | |
| 95 | + REL_MOD_PATH `::` `{` IMPORT_TREE_LIST `}` | |
| 96 | + REL_MOD_PATH [`as` IDENT] |
| 97 | +
|
| 98 | +IMPORT_TREE_LIST = Ø | (IMPORT_TREE `,`)* IMPORT_TREE [`,`] |
| 99 | +
|
| 100 | +REL_MOD_PATH = (IDENT `::`)* IDENT |
| 101 | +``` |
| 102 | + |
| 103 | +Resolution: |
| 104 | +First the import tree is prefixed with `::`, unless it already starts with |
| 105 | +`::`, `self` or `super`. |
| 106 | +Then resolution is performed as if the whole import tree were flattened, except |
| 107 | +that `{self}`/`{self as name}` are processed specially because `a::b::self` |
| 108 | +is illegal. |
| 109 | + |
| 110 | +```rust |
| 111 | +use a::{ |
| 112 | + b::{self as s, c, d as e}, |
| 113 | + f::*, |
| 114 | + g::h as i, |
| 115 | + *, |
| 116 | +}; |
| 117 | + |
| 118 | +=> |
| 119 | + |
| 120 | +use ::a::b as s; |
| 121 | +use ::a::b::c; |
| 122 | +use ::a::b::d as e; |
| 123 | +use ::a::f::*; |
| 124 | +use ::a::g::h as i; |
| 125 | +use ::a::*; |
| 126 | +``` |
| 127 | + |
| 128 | +Various corner cases are resolved naturally through desugaring |
| 129 | +```rust |
| 130 | +use an::{*, *}; // Use an owl! |
| 131 | + |
| 132 | +=> |
| 133 | + |
| 134 | +use an::*; |
| 135 | +use an::*; // Legal, but reported as unused by `unused_imports` lint. |
| 136 | +``` |
| 137 | + |
| 138 | +# Relationships with other proposal |
| 139 | + |
| 140 | +This RFC is an incremental improvement largely independent from other |
| 141 | +import-related proposals, but it can have effect on some other RFCs. |
| 142 | + |
| 143 | +Some RFCs propose new syntaxes for absolute paths in the current crate |
| 144 | +and paths from other crates. Some arguments in those proposals are based on |
| 145 | +usage statistics - "imports from other crates are more common" or "imports from |
| 146 | +the current crate are more common". More common imports are supposed to get |
| 147 | +less verbose syntax. |
| 148 | + |
| 149 | +This RFC removes the these statistics from the equation by reducing verbosity |
| 150 | +for all imports with common prefix. |
| 151 | +For example, the difference in verbosity between `A`, `B` and |
| 152 | +`C` is minimal and doesn't depend on the number of imports. |
| 153 | +```rust |
| 154 | +// A |
| 155 | +use extern::{ |
| 156 | + a::b::c, |
| 157 | + d::e::f, |
| 158 | + g::h::i, |
| 159 | +}; |
| 160 | +// B |
| 161 | +use crate::{ |
| 162 | + a::b::c, |
| 163 | + d::e::f, |
| 164 | + g::h::i, |
| 165 | +}; |
| 166 | +// C |
| 167 | +use { |
| 168 | + a::b::c, |
| 169 | + d::e::f, |
| 170 | + g::h::i, |
| 171 | +}; |
| 172 | +``` |
| 173 | + |
| 174 | +# Drawbacks |
| 175 | +[drawbacks]: #drawbacks |
| 176 | + |
| 177 | +The feature encourages (but not requires) multi-line formatting of a single |
| 178 | +import |
| 179 | +```rust |
| 180 | +use prefix::{ |
| 181 | + MyName, |
| 182 | + x::YourName, |
| 183 | + y::Surname, |
| 184 | +}; |
| 185 | +``` |
| 186 | +With this formatting it becomes harder to grep for `use.*MyName`. |
| 187 | + |
| 188 | +# Rationale and Alternatives |
| 189 | +[alternatives]: #alternatives |
| 190 | + |
| 191 | +Status quo is always an alternative. |
| 192 | + |
| 193 | +# Unresolved questions |
| 194 | +[unresolved]: #unresolved-questions |
| 195 | + |
| 196 | +None so far. |
0 commit comments