about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-01-26 18:21:47 +0100
committerGitHub <noreply@github.com>2019-01-26 18:21:47 +0100
commitbbe8dd9ca3b65d3ac024fc89876ae6216ef71517 (patch)
tree52fda633ebe785e1f4673ffb997cbe772034ac42
parent1206264fb222a4d868e21ecb5802602d4236a83a (diff)
parent1b659d69bc0ba7fe534cc26bda8544a558a7d2b2 (diff)
downloadrust-bbe8dd9ca3b65d3ac024fc89876ae6216ef71517.tar.gz
rust-bbe8dd9ca3b65d3ac024fc89876ae6216ef71517.zip
Rollup merge of #57908 - petrochenkov:errepice, r=estebank
resolve: Fix span arithmetics in the import conflict error

https://github.com/rust-lang/rust/pull/56937 rebased and fixed

Fixes https://github.com/rust-lang/rust/issues/56411
Fixes https://github.com/rust-lang/rust/issues/57071
Fixes https://github.com/rust-lang/rust/issues/57787

r? @estebank
-rw-r--r--src/librustc_resolve/lib.rs91
-rw-r--r--src/test/ui/issues/issue-56411.rs17
-rw-r--r--src/test/ui/issues/issue-56411.stderr31
-rw-r--r--src/test/ui/issues/issue_56411_aux.rs5
4 files changed, 98 insertions, 46 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 4c9347afa61..873ace90172 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -5134,60 +5134,59 @@ impl<'a> Resolver<'a> {
         );
 
         // See https://github.com/rust-lang/rust/issues/32354
-        if old_binding.is_import() || new_binding.is_import() {
-            let binding = if new_binding.is_import() && !new_binding.span.is_dummy() {
-                new_binding
+        let directive = match (&new_binding.kind, &old_binding.kind) {
+            (NameBindingKind::Import { directive, .. }, _) if !new_binding.span.is_dummy() =>
+                Some((directive, new_binding.span)),
+            (_, NameBindingKind::Import { directive, .. }) if !old_binding.span.is_dummy() =>
+                Some((directive, old_binding.span)),
+            _ => None,
+        };
+        if let Some((directive, binding_span)) = directive {
+            let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
+                format!("Other{}", name)
             } else {
-                old_binding
+                format!("other_{}", name)
             };
 
-            let cm = self.session.source_map();
-            let rename_msg = "you can use `as` to change the binding name of the import";
-
-            if let (
-                Ok(snippet),
-                NameBindingKind::Import { directive, ..},
-                _dummy @ false,
-            ) = (
-                cm.span_to_snippet(binding.span),
-                binding.kind.clone(),
-                binding.span.is_dummy(),
-            ) {
-                let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
-                    format!("Other{}", name)
-                } else {
-                    format!("other_{}", name)
-                };
+            let mut suggestion = None;
+            match directive.subclass {
+                ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } =>
+                    suggestion = Some(format!("self as {}", suggested_name)),
+                ImportDirectiveSubclass::SingleImport { source, .. } => {
+                    if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0)
+                                                         .map(|pos| pos as usize) {
+                        if let Ok(snippet) = self.session.source_map()
+                                                         .span_to_snippet(binding_span) {
+                            if pos <= snippet.len() {
+                                suggestion = Some(format!(
+                                    "{} as {}{}",
+                                    &snippet[..pos],
+                                    suggested_name,
+                                    if snippet.ends_with(";") { ";" } else { "" }
+                                ))
+                            }
+                        }
+                    }
+                }
+                ImportDirectiveSubclass::ExternCrate { source, target, .. } =>
+                    suggestion = Some(format!(
+                        "extern crate {} as {};",
+                        source.unwrap_or(target.name),
+                        suggested_name,
+                    )),
+                _ => unreachable!(),
+            }
 
+            let rename_msg = "you can use `as` to change the binding name of the import";
+            if let Some(suggestion) = suggestion {
                 err.span_suggestion_with_applicability(
-                    binding.span,
-                    &rename_msg,
-                    match directive.subclass {
-                        ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } =>
-                            format!("self as {}", suggested_name),
-                        ImportDirectiveSubclass::SingleImport { source, .. } =>
-                            format!(
-                                "{} as {}{}",
-                                &snippet[..((source.span.hi().0 - binding.span.lo().0) as usize)],
-                                suggested_name,
-                                if snippet.ends_with(";") {
-                                    ";"
-                                } else {
-                                    ""
-                                }
-                            ),
-                        ImportDirectiveSubclass::ExternCrate { source, target, .. } =>
-                            format!(
-                                "extern crate {} as {};",
-                                source.unwrap_or(target.name),
-                                suggested_name,
-                            ),
-                        _ => unreachable!(),
-                    },
+                    binding_span,
+                    rename_msg,
+                    suggestion,
                     Applicability::MaybeIncorrect,
                 );
             } else {
-                err.span_label(binding.span, rename_msg);
+                err.span_label(binding_span, rename_msg);
             }
         }
 
diff --git a/src/test/ui/issues/issue-56411.rs b/src/test/ui/issues/issue-56411.rs
new file mode 100644
index 00000000000..3561c21cc7e
--- /dev/null
+++ b/src/test/ui/issues/issue-56411.rs
@@ -0,0 +1,17 @@
+macro_rules! import {
+    ( $($name:ident),* ) => {
+        $(
+            mod $name;
+            pub use self::$name;
+            //~^ ERROR the name `issue_56411_aux` is defined multiple times
+            //~| ERROR `issue_56411_aux` is private, and cannot be re-exported
+
+        )*
+    }
+}
+
+import!(issue_56411_aux);
+
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/issues/issue-56411.stderr b/src/test/ui/issues/issue-56411.stderr
new file mode 100644
index 00000000000..dd05852c091
--- /dev/null
+++ b/src/test/ui/issues/issue-56411.stderr
@@ -0,0 +1,31 @@
+error[E0255]: the name `issue_56411_aux` is defined multiple times
+  --> $DIR/issue-56411.rs:5:21
+   |
+LL |             mod $name;
+   |             ---------- previous definition of the module `issue_56411_aux` here
+LL |             pub use self::$name;
+   |                     ^^^^^^^^^^^
+   |                     |
+   |                     `issue_56411_aux` reimported here
+   |                     you can use `as` to change the binding name of the import
+...
+LL | import!(issue_56411_aux);
+   | ------------------------- in this macro invocation
+   |
+   = note: `issue_56411_aux` must be defined only once in the type namespace of this module
+
+error[E0365]: `issue_56411_aux` is private, and cannot be re-exported
+  --> $DIR/issue-56411.rs:5:21
+   |
+LL |             pub use self::$name;
+   |                     ^^^^^^^^^^^ re-export of private `issue_56411_aux`
+...
+LL | import!(issue_56411_aux);
+   | ------------------------- in this macro invocation
+   |
+   = note: consider declaring type or module `issue_56411_aux` with `pub`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0255, E0365.
+For more information about an error, try `rustc --explain E0255`.
diff --git a/src/test/ui/issues/issue_56411_aux.rs b/src/test/ui/issues/issue_56411_aux.rs
new file mode 100644
index 00000000000..bd689e913ab
--- /dev/null
+++ b/src/test/ui/issues/issue_56411_aux.rs
@@ -0,0 +1,5 @@
+// compile-pass
+
+struct T {}
+
+fn main() {}