Skip to content

Commit

Permalink
Rollup merge of rust-lang#57908 - petrochenkov:errepice, r=estebank
Browse files Browse the repository at this point in the history
resolve: Fix span arithmetics in the import conflict error

rust-lang#56937 rebased and fixed

Fixes rust-lang#56411
Fixes rust-lang#57071
Fixes rust-lang#57787

r? @estebank
  • Loading branch information
Centril authored Jan 26, 2019
2 parents 20f57f3 + 1b659d6 commit e9eaebc
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 46 deletions.
91 changes: 45 additions & 46 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
17 changes: 17 additions & 0 deletions src/test/ui/issues/issue-56411.rs
Original file line number Diff line number Diff line change
@@ -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!");
}
31 changes: 31 additions & 0 deletions src/test/ui/issues/issue-56411.stderr
Original file line number Diff line number Diff line change
@@ -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`.
5 changes: 5 additions & 0 deletions src/test/ui/issues/issue_56411_aux.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// compile-pass

struct T {}

fn main() {}

0 comments on commit e9eaebc

Please sign in to comment.