about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSeiichi Uchida <seuchida@gmail.com>2019-01-27 23:14:57 +0900
committerGitHub <noreply@github.com>2019-01-27 23:14:57 +0900
commit36c9dc646cb01bedfbb49269ff96e94cf1397eee (patch)
tree68147c9d8bb073ed01220ec79dc8ef0f49ed04c3
parent5b6f6431a3d81026a1987f5081e64262ac96af82 (diff)
parent2125ad272e036c13547e6c6ff8cdfd0188c91fd7 (diff)
Merge pull request #3293 from scampi/issue-3241
Keep leading colons for global paths
-rw-r--r--README.md34
-rw-r--r--src/imports.rs24
-rw-r--r--tests/source/issue-3241.rs11
-rw-r--r--tests/target/issue-3241.rs11
4 files changed, 66 insertions, 14 deletions
diff --git a/README.md b/README.md
index 02e6892a2e0..acdb0b35ef8 100644
--- a/README.md
+++ b/README.md
@@ -15,24 +15,33 @@ the "travis example" badge above.
 
 You can run `rustfmt` with Rust 1.24 and above.
 
+### On the Stable toolchain
+
 To install:
 
-```
+```sh
 rustup component add rustfmt
 ```
 
-to run on a cargo project in the current working directory:
+To run on a cargo project in the current working directory:
 
-```
+```sh
 cargo fmt
 ```
 
-For the latest and greatest `rustfmt` (nightly required):
-```
+### On the Nightly toolchain
+
+For the latest and greatest `rustfmt`, nightly is required.
+
+To install:
+
+```sh
 rustup component add rustfmt --toolchain nightly
 ```
-To run:
-```
+
+To run on a cargo project in the current working directory:
+
+```sh
 cargo +nightly fmt
 ```
 
@@ -67,7 +76,7 @@ because in the future Rustfmt might work on code where it currently does not):
 
 ## Installation
 
-```
+```sh
 rustup component add rustfmt
 ```
 
@@ -75,7 +84,7 @@ rustup component add rustfmt
 
 To install from source (nightly required), first checkout to the tag or branch you want to install, then issue
 
-```
+```sh
 cargo install --path .
 ```
 
@@ -161,6 +170,11 @@ Configuration options are either stable or unstable. Stable options can always
 be used, while unstable ones are only available on a nightly toolchain, and opt-in.
 See [Configurations.md](Configurations.md) for details.
 
+### Rust's Editions
+
+Rustfmt is able to pick up the edition used by reading the `Cargo.toml` file if
+executed through the Cargo's formatting tool `cargo fmt`. Otherwise, the edition
+needs to be specified in `rustfmt.toml`, e.g., with `edition = "2018"`.
 
 ## Tips
 
@@ -178,7 +192,7 @@ See [Configurations.md](Configurations.md) for details.
 
   Example:
 
-  ```
+  ```sh
   cargo fmt -- --emit files
   ```
 
diff --git a/src/imports.rs b/src/imports.rs
index f8721456aa7..dea8fdf313f 100644
--- a/src/imports.rs
+++ b/src/imports.rs
@@ -324,9 +324,8 @@ impl UseTree {
             attrs,
         };
 
-        let leading_modsep = context.config.edition() == Edition::Edition2018
-            && a.prefix.to_string().len() > 2
-            && a.prefix.to_string().starts_with("::");
+        let leading_modsep =
+            context.config.edition() == Edition::Edition2018 && a.prefix.is_global();
 
         let mut modsep = leading_modsep;
 
@@ -339,6 +338,10 @@ impl UseTree {
 
         match a.kind {
             UseTreeKind::Glob => {
+                // in case of a global path and the glob starts at the root, e.g., "::*"
+                if a.prefix.segments.len() == 1 && leading_modsep {
+                    result.path.push(UseSegment::Ident("".to_owned(), None));
+                }
                 result.path.push(UseSegment::Glob);
             }
             UseTreeKind::Nested(ref list) => {
@@ -357,6 +360,11 @@ impl UseTree {
                     false,
                 )
                 .collect();
+                // in case of a global path and the nested list starts at the root,
+                // e.g., "::{foo, bar}"
+                if a.prefix.segments.len() == 1 && leading_modsep {
+                    result.path.push(UseSegment::Ident("".to_owned(), None));
+                }
                 result.path.push(UseSegment::List(
                     list.iter()
                         .zip(items.into_iter())
@@ -367,7 +375,15 @@ impl UseTree {
                 ));
             }
             UseTreeKind::Simple(ref rename, ..) => {
-                let name = rewrite_ident(context, path_to_imported_ident(&a.prefix)).to_owned();
+                // If the path has leading double colons and is composed of only 2 segments, then we
+                // bypass the call to path_to_imported_ident which would get only the ident and
+                // lose the path root, e.g., `that` in `::that`.
+                // The span of `a.prefix` contains the leading colons.
+                let name = if a.prefix.segments.len() == 2 && leading_modsep {
+                    context.snippet(a.prefix.span).to_owned()
+                } else {
+                    rewrite_ident(context, path_to_imported_ident(&a.prefix)).to_owned()
+                };
                 let alias = rename.and_then(|ident| {
                     if ident.name == "_" {
                         // for impl-only-use
diff --git a/tests/source/issue-3241.rs b/tests/source/issue-3241.rs
new file mode 100644
index 00000000000..090284a21fd
--- /dev/null
+++ b/tests/source/issue-3241.rs
@@ -0,0 +1,11 @@
+// rustfmt-edition: 2018
+
+use ::ignore;
+use ::ignore::some::more;
+use ::{foo, bar};
+use ::*;
+use ::baz::{foo, bar};
+
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/tests/target/issue-3241.rs b/tests/target/issue-3241.rs
new file mode 100644
index 00000000000..60b452abdde
--- /dev/null
+++ b/tests/target/issue-3241.rs
@@ -0,0 +1,11 @@
+// rustfmt-edition: 2018
+
+use ::baz::{bar, foo};
+use ::ignore;
+use ::ignore::some::more;
+use ::*;
+use ::{bar, foo};
+
+fn main() {
+    println!("Hello, world!");
+}