about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_resolve/error_reporting.rs57
-rw-r--r--src/librustc_resolve/lib.rs11
-rw-r--r--src/librustc_resolve/resolve_imports.rs12
-rw-r--r--src/test/ui/issue-59764.fixed134
-rw-r--r--src/test/ui/issue-59764.rs1
-rw-r--r--src/test/ui/issue-59764.stderr61
6 files changed, 68 insertions, 208 deletions
diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs
index 5372c4ee44b..931bce91d7d 100644
--- a/src/librustc_resolve/error_reporting.rs
+++ b/src/librustc_resolve/error_reporting.rs
@@ -617,14 +617,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                 _ => format!("{}", ident),
             };
 
-            // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
-            // intermediate segments.
-            let (mut span, mut correction) = (directive.span,
-                                              format!("{}::{}", module_name, import));
-
-            if directive.is_nested() {
-                span = directive.use_span;
-
+            let mut corrections: Vec<(Span, String)> = Vec::new();
+            if !directive.is_nested() {
+                // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
+                // intermediate segments.
+                corrections.push((directive.span, format!("{}::{}", module_name, import)));
+            } else {
                 // Find the binding span (and any trailing commas and spaces).
                 //   ie. `use a::b::{c, d, e};`
                 //                      ^^^
@@ -652,6 +650,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                 }
                 debug!("check_for_module_export_macro: removal_span={:?}", removal_span);
 
+                // Remove the `removal_span`.
+                corrections.push((removal_span, "".to_string()));
+
                 // Find the span after the crate name and if it has nested imports immediatately
                 // after the crate name already.
                 //   ie. `use a::b::{c, d};`
@@ -666,34 +667,32 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
 
                 let source_map = self.resolver.session.source_map();
 
-                // Remove two bytes at the end to keep all but the `};` characters.
-                //   ie. `{b::{c, d}, e::{f, g}};`
-                //        ^^^^^^^^^^^^^^^^^^^^^
-                let end_bytes = BytePos(if has_nested { 2 } else { 1 });
-                let mut remaining_span = after_crate_name.with_hi(
-                    after_crate_name.hi() - end_bytes);
-                if has_nested {
-                    // Remove two bytes at the start to keep all but the initial `{` character.
-                    //   ie. `{b::{c, d}, e::{f, g}`
-                    //         ^^^^^^^^^^^^^^^^^^^^
-                    remaining_span = remaining_span.with_lo(after_crate_name.lo() + BytePos(1));
+                // Add the import to the start, with a `{` if required.
+                let start_point = source_map.start_point(after_crate_name);
+                if let Ok(start_snippet) = source_map.span_to_snippet(start_point) {
+                    corrections.push((
+                        start_point,
+                        if has_nested {
+                            // In this case, `start_snippet` must equal '{'.
+                            format!("{}{}, ", start_snippet, import)
+                        } else {
+                            // In this case, add a `{`, then the moved import, then whatever
+                            // was there before.
+                            format!("{{{}, {}", import, start_snippet)
+                        }
+                    ));
                 }
 
-                // Calculate the number of characters into a snippet to remove the removal
-                // span.
-                let lo = removal_span.lo() - remaining_span.lo();
-                let hi = lo + (removal_span.hi() - removal_span.lo());
-                if let Ok(mut remaining) = source_map.span_to_snippet(remaining_span) {
-                    // Remove the original location of the binding.
-                    remaining.replace_range((lo.0 as usize)..(hi.0 as usize), "");
-                    correction = format!("use {}::{{{}, {}}};", module_name, import, remaining);
+                // Add a `};` to the end if nested, matching the `{` added at the start.
+                if !has_nested {
+                    corrections.push((source_map.end_point(after_crate_name),
+                                     "};".to_string()));
                 }
             }
 
             let suggestion = Some((
-                span,
+                corrections,
                 String::from("a macro with this name exists at the root of the crate"),
-                correction,
                 Applicability::MaybeIncorrect,
             ));
             let note = vec![
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index b33356c2ba7..c1353d771c2 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -139,8 +139,8 @@ impl Ord for BindingError {
     }
 }
 
-/// A span, message, replacement text, and applicability.
-type Suggestion = (Span, String, String, Applicability);
+/// A vector of spans and replacements, a message and applicability.
+type Suggestion = (Vec<(Span, String)>, String, Applicability);
 
 enum ResolutionError<'a> {
     /// Error E0401: can't use type or const parameters from outer function.
@@ -390,8 +390,8 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                                            "failed to resolve: {}", &label);
             err.span_label(span, label);
 
-            if let Some((span, msg, suggestion, applicability)) = suggestion {
-                err.span_suggestion(span, &msg, suggestion, applicability);
+            if let Some((suggestions, msg, applicability)) = suggestion {
+                err.multipart_suggestion(&msg, suggestions, applicability);
             }
 
             err
@@ -3774,9 +3774,8 @@ impl<'a> Resolver<'a> {
                             (
                                 String::from("unresolved import"),
                                 Some((
-                                    ident.span,
+                                    vec![(ident.span, candidate.path.to_string())],
                                     String::from("a similar path exists"),
-                                    candidate.path.to_string(),
                                     Applicability::MaybeIncorrect,
                                 )),
                             )
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index ef5f0f54ee3..62af6e19603 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -793,8 +793,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                 diag.span_label(err.span, label);
             }
 
-            if let Some((span, msg, suggestion, applicability)) = err.suggestion {
-                diag.span_suggestion(span, &msg, suggestion, applicability);
+            if let Some((suggestions, msg, applicability)) = err.suggestion {
+                diag.multipart_suggestion(&msg, suggestions, applicability);
             }
         }
 
@@ -947,9 +947,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                                 label: None,
                                 note,
                                 suggestion: Some((
-                                    span,
+                                    vec![(span, Segment::names_to_string(&suggestion))],
                                     String::from("a similar path exists"),
-                                    Segment::names_to_string(&suggestion),
                                     Applicability::MaybeIncorrect,
                                 )),
                             }
@@ -1113,8 +1112,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
 
                 let lev_suggestion = find_best_match_for_name(names, &ident.as_str(), None)
                    .map(|suggestion|
-                        (ident.span, String::from("a similar name exists in the module"),
-                         suggestion.to_string(), Applicability::MaybeIncorrect)
+                        (vec![(ident.span, suggestion.to_string())],
+                         String::from("a similar name exists in the module"),
+                         Applicability::MaybeIncorrect)
                     );
 
                 let (suggestion, note) = match self.check_for_module_export_macro(
diff --git a/src/test/ui/issue-59764.fixed b/src/test/ui/issue-59764.fixed
deleted file mode 100644
index ad3bab50cfc..00000000000
--- a/src/test/ui/issue-59764.fixed
+++ /dev/null
@@ -1,134 +0,0 @@
-// aux-build:issue-59764.rs
-// compile-flags:--extern issue_59764
-// edition:2018
-// run-rustfix
-
-#![allow(warnings)]
-
-// This tests the suggestion to import macros from the root of a crate. This aims to capture
-// the case where a user attempts to import a macro from the definition location instead of the
-// root of the crate and the macro is annotated with `#![macro_export]`.
-
-// Edge cases..
-
-mod multiple_imports_same_line_at_end {
-    use issue_59764::{makro, foo::{baz}};
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod multiple_imports_multiline_at_end_trailing_comma {
-    use issue_59764::{makro, foo::{
-        baz,
-        //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-    }};
-}
-
-mod multiple_imports_multiline_at_end {
-    use issue_59764::{makro, foo::{
-        baz,
-        //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-    }};
-}
-
-mod multiple_imports_same_line_in_middle {
-    use issue_59764::{makro, foo::{baz, foobar}};
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod multiple_imports_multiline_in_middle_trailing_comma {
-    use issue_59764::{makro, foo::{
-        baz,
-        //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-        foobar,
-    }};
-}
-
-mod multiple_imports_multiline_in_middle {
-    use issue_59764::{makro, foo::{
-        baz,
-        //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-        foobar
-    }};
-}
-
-mod nested_imports {
-    use issue_59764::{makro, foobaz};
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod nested_multiple_imports {
-    use issue_59764::{makro, foobaz, foo::{baz}};
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod nested_multiline_multiple_imports_trailing_comma {
-    use issue_59764::{makro, 
-        foobaz,
-        foo::{
-            baz,
-            //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-        },
-    };
-}
-
-mod nested_multiline_multiple_imports {
-    use issue_59764::{makro, 
-        foobaz,
-        foo::{
-            baz,
-            //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-        }
-    };
-}
-
-mod doubly_nested_multiple_imports {
-    use issue_59764::{makro, foobaz, foo::{baz, barbaz::{barfoo}}};
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod doubly_multiline_nested_multiple_imports {
-    use issue_59764::{makro, 
-        foobaz,
-        foo::{
-            baz,
-            //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-            barbaz::{
-                barfoo,
-            }
-        }
-    };
-}
-
-mod renamed_import {
-    use issue_59764::makro as baz;
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod renamed_multiple_imports {
-    use issue_59764::{makro as foobar, foo::{baz}};
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod lots_of_whitespace {
-    use issue_59764::{makro as foobar, 
-
-            foobaz,
-
-
-            foo::{baz} //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-
-        };
-}
-
-// Simple case..
-
-use issue_59764::makro;
-//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-
-makro!(bar);
-//~^ ERROR cannot determine resolution for the macro `makro`
-
-fn main() {
-    bar();
-    //~^ ERROR cannot find function `bar` in this scope [E0425]
-}
diff --git a/src/test/ui/issue-59764.rs b/src/test/ui/issue-59764.rs
index 0c6787691de..09dee8c2732 100644
--- a/src/test/ui/issue-59764.rs
+++ b/src/test/ui/issue-59764.rs
@@ -1,7 +1,6 @@
 // aux-build:issue-59764.rs
 // compile-flags:--extern issue_59764
 // edition:2018
-// run-rustfix
 
 #![allow(warnings)]
 
diff --git a/src/test/ui/issue-59764.stderr b/src/test/ui/issue-59764.stderr
index 89b1f84605d..924e69f5f97 100644
--- a/src/test/ui/issue-59764.stderr
+++ b/src/test/ui/issue-59764.stderr
@@ -1,5 +1,5 @@
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:15:33
+  --> $DIR/issue-59764.rs:14:33
    |
 LL |     use issue_59764::foo::{baz, makro};
    |                                 ^^^^^ no `makro` in `foo`
@@ -8,10 +8,10 @@ LL |     use issue_59764::foo::{baz, makro};
 help: a macro with this name exists at the root of the crate
    |
 LL |     use issue_59764::{makro, foo::{baz}};
-   |
+   |                      ^^^^^^^^^       --^^
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:22:9
+  --> $DIR/issue-59764.rs:21:9
    |
 LL |         makro,
    |         ^^^^^ no `makro` in `foo`
@@ -26,7 +26,7 @@ LL |     }};
    |
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:29:9
+  --> $DIR/issue-59764.rs:28:9
    |
 LL |         makro
    |         ^^^^^ no `makro` in `foo`
@@ -41,7 +41,7 @@ LL |     }};
    |
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:34:33
+  --> $DIR/issue-59764.rs:33:33
    |
 LL |     use issue_59764::foo::{baz, makro, foobar};
    |                                 ^^^^^ no `makro` in `foo`
@@ -50,10 +50,10 @@ LL |     use issue_59764::foo::{baz, makro, foobar};
 help: a macro with this name exists at the root of the crate
    |
 LL |     use issue_59764::{makro, foo::{baz, foobar}};
-   |
+   |                      ^^^^^^^^^         --      ^^
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:41:9
+  --> $DIR/issue-59764.rs:40:9
    |
 LL |         makro,
    |         ^^^^^ no `makro` in `foo`
@@ -69,7 +69,7 @@ LL |     }};
    |
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:49:9
+  --> $DIR/issue-59764.rs:48:9
    |
 LL |         makro,
    |         ^^^^^ no `makro` in `foo`
@@ -85,7 +85,7 @@ LL |     }};
    |
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:55:31
+  --> $DIR/issue-59764.rs:54:31
    |
 LL |     use issue_59764::{foobaz, foo::makro};
    |                               ^^^^^^^^^^ no `makro` in `foo`
@@ -94,10 +94,10 @@ LL |     use issue_59764::{foobaz, foo::makro};
 help: a macro with this name exists at the root of the crate
    |
 LL |     use issue_59764::{makro, foobaz};
-   |
+   |                      ^^^^^^^      --
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:60:42
+  --> $DIR/issue-59764.rs:59:42
    |
 LL |     use issue_59764::{foobaz, foo::{baz, makro}};
    |                                          ^^^^^ no `makro` in `foo`
@@ -106,10 +106,10 @@ LL |     use issue_59764::{foobaz, foo::{baz, makro}};
 help: a macro with this name exists at the root of the crate
    |
 LL |     use issue_59764::{makro, foobaz, foo::{baz}};
-   |
+   |                      ^^^^^^^                 --
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:69:13
+  --> $DIR/issue-59764.rs:68:13
    |
 LL |             makro,
    |             ^^^^^ no `makro` in `foo`
@@ -122,11 +122,10 @@ LL |         foobaz,
 LL |         foo::{
 LL |             baz,
 LL |
-LL |         },
- ...
+   |
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:79:13
+  --> $DIR/issue-59764.rs:78:13
    |
 LL |             makro
    |             ^^^^^ no `makro` in `foo`
@@ -139,11 +138,10 @@ LL |         foobaz,
 LL |         foo::{
 LL |             baz,
 LL |
-LL |         }
- ...
+   |
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:85:42
+  --> $DIR/issue-59764.rs:84:42
    |
 LL |     use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}};
    |                                          ^^^^^ no `makro` in `foo`
@@ -152,10 +150,10 @@ LL |     use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}};
 help: a macro with this name exists at the root of the crate
    |
 LL |     use issue_59764::{makro, foobaz, foo::{baz, barbaz::{barfoo}}};
-   |
+   |                      ^^^^^^^                   --
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:94:13
+  --> $DIR/issue-59764.rs:93:13
    |
 LL |             makro,
    |             ^^^^^ no `makro` in `foo`
@@ -168,11 +166,10 @@ LL |         foobaz,
 LL |         foo::{
 LL |             baz,
 LL |
-LL |             barbaz::{
- ...
+   |
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:103:9
+  --> $DIR/issue-59764.rs:102:9
    |
 LL |     use issue_59764::foo::makro as baz;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo`
@@ -184,7 +181,7 @@ LL |     use issue_59764::makro as baz;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:108:33
+  --> $DIR/issue-59764.rs:107:33
    |
 LL |     use issue_59764::foo::{baz, makro as foobar};
    |                                 ^^^^^^^^^^^^^^^ no `makro` in `foo`
@@ -193,10 +190,10 @@ LL |     use issue_59764::foo::{baz, makro as foobar};
 help: a macro with this name exists at the root of the crate
    |
 LL |     use issue_59764::{makro as foobar, foo::{baz}};
-   |
+   |                      ^^^^^^^^^^^^^^^^^^^       --^^
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:121:17
+  --> $DIR/issue-59764.rs:120:17
    |
 LL |                 makro as foobar}
    |                 ^^^^^^^^^^^^^^^ no `makro` in `foo`
@@ -204,16 +201,16 @@ LL |                 makro as foobar}
    = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
 help: a macro with this name exists at the root of the crate
    |
-LL |     use issue_59764::{makro as foobar, 
+LL |         issue_59764::{makro as foobar, 
 LL | 
 LL |             foobaz,
 LL | 
 LL | 
 LL |             foo::{baz}
- ...
+   |
 
 error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:128:5
+  --> $DIR/issue-59764.rs:127:5
    |
 LL | use issue_59764::foo::makro;
    |     ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo`
@@ -225,7 +222,7 @@ LL | use issue_59764::makro;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: cannot determine resolution for the macro `makro`
-  --> $DIR/issue-59764.rs:131:1
+  --> $DIR/issue-59764.rs:130:1
    |
 LL | makro!(bar);
    | ^^^^^
@@ -233,7 +230,7 @@ LL | makro!(bar);
    = note: import resolution is stuck, try simplifying macro imports
 
 error[E0425]: cannot find function `bar` in this scope
-  --> $DIR/issue-59764.rs:135:5
+  --> $DIR/issue-59764.rs:134:5
    |
 LL |     bar();
    |     ^^^ not found in this scope