From 9eacd68a4945aaba244885c330f64004da58a408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franc=CC=A7ois=20Mockers?= Date: Sun, 21 Oct 2018 00:23:29 +0200 Subject: [PATCH] manage cases with tabs or other whitespaces --- src/librustc_resolve/build_reduced_graph.rs | 5 +- src/librustc_resolve/check_unused.rs | 2 +- src/librustc_resolve/lib.rs | 55 ++++++++++++------- src/librustc_resolve/resolve_imports.rs | 7 ++- src/test/ui/issues/issue-45829/import-self.rs | 22 ++++++++ .../ui/issues/issue-45829/import-self.stderr | 31 +++++++++++ .../ui/issues/issue-45829/import-twice.rs | 18 ++++++ .../ui/issues/issue-45829/import-twice.stderr | 17 ++++++ .../issue-45829/rename-extern-with-tab.rs | 17 ++++++ .../issue-45829/rename-extern-with-tab.stderr | 17 ++++++ .../issue-45829/rename-use-with-tabs.rs | 21 +++++++ .../issue-45829/rename-use-with-tabs.stderr | 17 ++++++ ...solve-conflict-item-vs-extern-crate.stderr | 4 -- 13 files changed, 204 insertions(+), 29 deletions(-) create mode 100644 src/test/ui/issues/issue-45829/import-self.rs create mode 100644 src/test/ui/issues/issue-45829/import-self.stderr create mode 100644 src/test/ui/issues/issue-45829/import-twice.rs create mode 100644 src/test/ui/issues/issue-45829/import-twice.stderr create mode 100644 src/test/ui/issues/issue-45829/rename-extern-with-tab.rs create mode 100644 src/test/ui/issues/issue-45829/rename-extern-with-tab.stderr create mode 100644 src/test/ui/issues/issue-45829/rename-use-with-tabs.rs create mode 100644 src/test/ui/issues/issue-45829/rename-use-with-tabs.stderr diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 25a7ff9cd3f..4158d20a5f8 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -449,7 +449,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> { id: item.id, parent, imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), - subclass: ImportDirectiveSubclass::ExternCrate(orig_name), + subclass: ImportDirectiveSubclass::ExternCrate { + source: orig_name, + target: ident, + }, root_span: item.span, span: item.span, module_path: Vec::new(), diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index de9481579e2..5fa0460a28d 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -144,7 +144,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) { } } } - ImportDirectiveSubclass::ExternCrate(_) => { + ImportDirectiveSubclass::ExternCrate { .. } => { resolver.maybe_unused_extern_crates.push((directive.id, directive.span)); } ImportDirectiveSubclass::MacroUse => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c1d1f3c5e0d..ba367cca245 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1234,7 +1234,7 @@ impl<'a> NameBinding<'a> { match self.kind { NameBindingKind::Import { directive: &ImportDirective { - subclass: ImportDirectiveSubclass::ExternCrate(_), .. + subclass: ImportDirectiveSubclass::ExternCrate { .. }, .. }, .. } => true, _ => false, @@ -3794,7 +3794,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { if let NameBindingKind::Import { directive: d, .. } = binding.kind { // Careful: we still want to rewrite paths from // renamed extern crates. - if let ImportDirectiveSubclass::ExternCrate(None) = d.subclass { + if let ImportDirectiveSubclass::ExternCrate { source: None, .. } = d.subclass { return } } @@ -4776,7 +4776,15 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { 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) = cm.span_to_snippet(binding.span) { + if let ( + Ok(snippet), + NameBindingKind::Import { directive, ..}, + _x @ 1 ... std::u32::MAX, + ) = ( + cm.span_to_snippet(binding.span), + binding.kind.clone(), + binding.span.hi().0, + ) { let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { format!("Other{}", name) } else { @@ -4785,24 +4793,29 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { err.span_suggestion_with_applicability( binding.span, - rename_msg, - match ( - snippet.split_whitespace().find(|w| *w == "as"), - snippet.ends_with(";") - ) { - (Some(_), false) => format!("{} as {}", - &snippet[..snippet.find(" as ").unwrap()], - suggested_name, - ), - (Some(_), true) => format!("{} as {};", - &snippet[..snippet.find(" as ").unwrap()], - suggested_name, - ), - (None, false) => format!("{} as {}", snippet, suggested_name), - (None, true) => format!("{} as {};", - &snippet[..snippet.len() - 1], - suggested_name - ), + &rename_msg, + match (&directive.subclass, snippet.ends_with(";"), snippet.as_ref()) { + (ImportDirectiveSubclass::SingleImport { .. }, false, "self") => + format!("self as {}", suggested_name), + (ImportDirectiveSubclass::SingleImport { source, .. }, false, _) => + format!( + "{} as {}", + &snippet[..((source.span.hi().0 - binding.span.lo().0) as usize)], + suggested_name, + ), + (ImportDirectiveSubclass::SingleImport { source, .. }, true, _) => + format!( + "{} as {};", + &snippet[..((source.span.hi().0 - binding.span.lo().0) as usize)], + suggested_name, + ), + (ImportDirectiveSubclass::ExternCrate { source, target, .. }, _, _) => + format!( + "extern crate {} as {};", + source.unwrap_or(target.name), + suggested_name, + ), + (_, _, _) => unreachable!(), }, Applicability::MaybeIncorrect, ); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 6e9877b1ab6..bb51bf95051 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -52,7 +52,10 @@ pub enum ImportDirectiveSubclass<'a> { max_vis: Cell, // The visibility of the greatest re-export. // n.b. `max_vis` is only used in `finalize_import` to check for re-export errors. }, - ExternCrate(Option), + ExternCrate { + source: Option, + target: Ident, + }, MacroUse, } @@ -1342,7 +1345,7 @@ fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass) -> St match *subclass { SingleImport { source, .. } => source.to_string(), GlobImport { .. } => "*".to_string(), - ExternCrate(_) => "".to_string(), + ExternCrate { .. } => "".to_string(), MacroUse => "#[macro_use]".to_string(), } } diff --git a/src/test/ui/issues/issue-45829/import-self.rs b/src/test/ui/issues/issue-45829/import-self.rs new file mode 100644 index 00000000000..8b13ffd0076 --- /dev/null +++ b/src/test/ui/issues/issue-45829/import-self.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod foo { + pub struct A; + pub struct B; +} + +use foo::{self}; + +use foo as self; + +use foo::self; + +fn main() {} diff --git a/src/test/ui/issues/issue-45829/import-self.stderr b/src/test/ui/issues/issue-45829/import-self.stderr new file mode 100644 index 00000000000..985dc4e7131 --- /dev/null +++ b/src/test/ui/issues/issue-45829/import-self.stderr @@ -0,0 +1,31 @@ +error: expected identifier, found keyword `self` + --> $DIR/import-self.rs:18:12 + | +LL | use foo as self; + | ^^^^ expected identifier, found keyword + +error[E0429]: `self` imports are only allowed within a { } list + --> $DIR/import-self.rs:20:5 + | +LL | use foo::self; + | ^^^^^^^^^ + +error[E0255]: the name `foo` is defined multiple times + --> $DIR/import-self.rs:16:11 + | +LL | mod foo { + | ------- previous definition of the module `foo` here +... +LL | use foo::{self}; + | ^^^^ `foo` reimported here + | + = note: `foo` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::{self as other_foo}; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors occurred: E0255, E0429. +For more information about an error, try `rustc --explain E0255`. diff --git a/src/test/ui/issues/issue-45829/import-twice.rs b/src/test/ui/issues/issue-45829/import-twice.rs new file mode 100644 index 00000000000..785932e5ef4 --- /dev/null +++ b/src/test/ui/issues/issue-45829/import-twice.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod foo { + pub struct A; + pub struct B; +} + +use foo::{A, A}; + +fn main() {} diff --git a/src/test/ui/issues/issue-45829/import-twice.stderr b/src/test/ui/issues/issue-45829/import-twice.stderr new file mode 100644 index 00000000000..566d47965f8 --- /dev/null +++ b/src/test/ui/issues/issue-45829/import-twice.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `A` is defined multiple times + --> $DIR/import-twice.rs:16:14 + | +LL | use foo::{A, A}; + | - ^ `A` reimported here + | | + | previous import of the type `A` here + | + = note: `A` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::{A, A as OtherA}; + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/issues/issue-45829/rename-extern-with-tab.rs b/src/test/ui/issues/issue-45829/rename-extern-with-tab.rs new file mode 100644 index 00000000000..7066ed65c78 --- /dev/null +++ b/src/test/ui/issues/issue-45829/rename-extern-with-tab.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:issue_45829_a.rs +// aux-build:issue_45829_b.rs + +extern crate issue_45829_a; +extern crate issue_45829_b as issue_45829_a; + +fn main() {} diff --git a/src/test/ui/issues/issue-45829/rename-extern-with-tab.stderr b/src/test/ui/issues/issue-45829/rename-extern-with-tab.stderr new file mode 100644 index 00000000000..769be545706 --- /dev/null +++ b/src/test/ui/issues/issue-45829/rename-extern-with-tab.stderr @@ -0,0 +1,17 @@ +error[E0259]: the name `issue_45829_a` is defined multiple times + --> $DIR/rename-extern-with-tab.rs:15:1 + | +LL | extern crate issue_45829_a; + | --------------------------- previous import of the extern crate `issue_45829_a` here +LL | extern crate issue_45829_b as issue_45829_a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_45829_a` reimported here + | + = note: `issue_45829_a` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate issue_45829_b as other_issue_45829_a; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/src/test/ui/issues/issue-45829/rename-use-with-tabs.rs b/src/test/ui/issues/issue-45829/rename-use-with-tabs.rs new file mode 100644 index 00000000000..c1e4d908906 --- /dev/null +++ b/src/test/ui/issues/issue-45829/rename-use-with-tabs.rs @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod foo { + pub struct A; + + pub mod bar { + pub struct B; + } +} + +use foo::{A, bar::B as A}; + +fn main() {} diff --git a/src/test/ui/issues/issue-45829/rename-use-with-tabs.stderr b/src/test/ui/issues/issue-45829/rename-use-with-tabs.stderr new file mode 100644 index 00000000000..b80a692028a --- /dev/null +++ b/src/test/ui/issues/issue-45829/rename-use-with-tabs.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `A` is defined multiple times + --> $DIR/rename-use-with-tabs.rs:19:14 + | +LL | use foo::{A, bar::B as A}; + | - ^^^^^^^^^^^^^^^^^ `A` reimported here + | | + | previous import of the type `A` here + | + = note: `A` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::{A, bar::B as OtherA}; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr b/src/test/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr index 8e0baf3be6f..0b082c1105f 100644 --- a/src/test/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr +++ b/src/test/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr @@ -5,10 +5,6 @@ LL | mod std {} //~ ERROR the name `std` is defined multiple times | ^^^^^^^ `std` redefined here | = note: `std` must be defined only once in the type namespace of this module -help: you can use `as` to change the binding name of the import - | -LL | as other_std// Copyright 2014 The Rust Project Developers. See the COPYRIGHT - | ^^^^^^^^^^^^ error: aborting due to previous error