From e9d8d238ef76c7991b316bbfbd9f857d84bd39cf Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 12 Nov 2022 21:46:05 -0700 Subject: [PATCH 1/4] diagnostics: suggest changing `s@self::{macro}@::macro` for exported Fixes #99695 --- compiler/rustc_resolve/src/diagnostics.rs | 30 ++++++++++++++++++++++- tests/ui/imports/issue-99695.fixed | 17 +++++++++++++ tests/ui/imports/issue-99695.rs | 16 ++++++++++++ tests/ui/imports/issue-99695.stderr | 16 ++++++++++++ 4 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 tests/ui/imports/issue-99695.fixed create mode 100644 tests/ui/imports/issue-99695.rs create mode 100644 tests/ui/imports/issue-99695.stderr diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index f24e405018b74..2a5cc288380f4 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2125,9 +2125,31 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let source_map = self.r.session.source_map(); + // Make sure this is actually crate-relative. + let use_and_crate = import.use_span.with_hi(after_crate_name.lo()); + let is_definitely_crate = + source_map.span_to_snippet(use_and_crate).map_or(false, |s| { + let mut s = s.trim(); + debug!("check_for_module_export_macro: s={s:?}",); + s = s + .split_whitespace() + .rev() + .next() + .expect("split_whitespace always yields at least once"); + debug!("check_for_module_export_macro: s={s:?}",); + if s.ends_with("::") { + s = &s[..s.len() - 2]; + } else { + return false; + } + s = s.trim(); + debug!("check_for_module_export_macro: s={s:?}",); + s != "self" && s != "super" + }); + // 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) { + if is_definitely_crate && let Ok(start_snippet) = source_map.span_to_snippet(start_point) { corrections.push(( start_point, if has_nested { @@ -2139,6 +2161,12 @@ impl<'a, 'b> ImportResolver<'a, 'b> { format!("{{{}, {}", import_snippet, start_snippet) }, )); + } else { + // If the root import is module-relative, add the import separately + corrections.push(( + source_map.start_point(import.use_span).shrink_to_lo(), + format!("use {module_name}::{import_snippet};\n"), + )); } // Add a `};` to the end if nested, matching the `{` added at the start. diff --git a/tests/ui/imports/issue-99695.fixed b/tests/ui/imports/issue-99695.fixed new file mode 100644 index 0000000000000..6bf228b23aad2 --- /dev/null +++ b/tests/ui/imports/issue-99695.fixed @@ -0,0 +1,17 @@ +// run-rustfix +#![allow(unused, nonstandard_style)] +mod m { + #[macro_export] + macro_rules! nu { + {} => {}; + } + + pub struct other_item; + + use ::nu; +pub use self::{other_item as _}; + //~^ ERROR unresolved import `self::nu` [E0432] + //~| HELP a macro with this name exists at the root of the crate +} + +fn main() {} diff --git a/tests/ui/imports/issue-99695.rs b/tests/ui/imports/issue-99695.rs new file mode 100644 index 0000000000000..f7199f1497ab0 --- /dev/null +++ b/tests/ui/imports/issue-99695.rs @@ -0,0 +1,16 @@ +// run-rustfix +#![allow(unused, nonstandard_style)] +mod m { + #[macro_export] + macro_rules! nu { + {} => {}; + } + + pub struct other_item; + + pub use self::{nu, other_item as _}; + //~^ ERROR unresolved import `self::nu` [E0432] + //~| HELP a macro with this name exists at the root of the crate +} + +fn main() {} diff --git a/tests/ui/imports/issue-99695.stderr b/tests/ui/imports/issue-99695.stderr new file mode 100644 index 0000000000000..0ef762e1c8230 --- /dev/null +++ b/tests/ui/imports/issue-99695.stderr @@ -0,0 +1,16 @@ +error[E0432]: unresolved import `self::nu` + --> $DIR/issue-99695.rs:11:20 + | +LL | pub use self::{nu, other_item as _}; + | ^^ no `nu` in `m` + | + = 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 ::nu; +LL ~ pub use self::{other_item as _}; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. From e237690a28f0d38ab478616fe4b247fb6eb8013f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 12 Nov 2022 22:08:07 -0700 Subject: [PATCH 2/4] diagnostics: add `};` only if `{` was added too --- compiler/rustc_resolve/src/diagnostics.rs | 10 +++++----- tests/ui/imports/issue-99695-b.fixed | 20 ++++++++++++++++++++ tests/ui/imports/issue-99695-b.rs | 19 +++++++++++++++++++ tests/ui/imports/issue-99695-b.stderr | 16 ++++++++++++++++ 4 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 tests/ui/imports/issue-99695-b.fixed create mode 100644 tests/ui/imports/issue-99695-b.rs create mode 100644 tests/ui/imports/issue-99695-b.stderr diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 2a5cc288380f4..af4d7a8eafff3 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2161,6 +2161,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> { format!("{{{}, {}", import_snippet, start_snippet) }, )); + + // 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())); + } } else { // If the root import is module-relative, add the import separately corrections.push(( @@ -2168,11 +2173,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> { format!("use {module_name}::{import_snippet};\n"), )); } - - // 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(( diff --git a/tests/ui/imports/issue-99695-b.fixed b/tests/ui/imports/issue-99695-b.fixed new file mode 100644 index 0000000000000..0e60c73b67a44 --- /dev/null +++ b/tests/ui/imports/issue-99695-b.fixed @@ -0,0 +1,20 @@ +// run-rustfix +#![allow(unused, nonstandard_style)] +mod m { + + mod p { + #[macro_export] + macro_rules! nu { + {} => {}; + } + + pub struct other_item; + } + + use ::nu; +pub use self::p::{other_item as _}; + //~^ ERROR unresolved import `self::p::nu` [E0432] + //~| HELP a macro with this name exists at the root of the crate +} + +fn main() {} diff --git a/tests/ui/imports/issue-99695-b.rs b/tests/ui/imports/issue-99695-b.rs new file mode 100644 index 0000000000000..031443a1f5df8 --- /dev/null +++ b/tests/ui/imports/issue-99695-b.rs @@ -0,0 +1,19 @@ +// run-rustfix +#![allow(unused, nonstandard_style)] +mod m { + + mod p { + #[macro_export] + macro_rules! nu { + {} => {}; + } + + pub struct other_item; + } + + pub use self::p::{nu, other_item as _}; + //~^ ERROR unresolved import `self::p::nu` [E0432] + //~| HELP a macro with this name exists at the root of the crate +} + +fn main() {} diff --git a/tests/ui/imports/issue-99695-b.stderr b/tests/ui/imports/issue-99695-b.stderr new file mode 100644 index 0000000000000..b6f5c726a5ca9 --- /dev/null +++ b/tests/ui/imports/issue-99695-b.stderr @@ -0,0 +1,16 @@ +error[E0432]: unresolved import `self::p::nu` + --> $DIR/issue-99695-b.rs:14:23 + | +LL | pub use self::p::{nu, other_item as _}; + | ^^ no `nu` in `m::p` + | + = 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 ::nu; +LL ~ pub use self::p::{other_item as _}; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. From dca160a06a85cfe6d961a586543112e772e55b13 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 6 Dec 2022 08:42:30 -0700 Subject: [PATCH 3/4] diagnostics: use `module_path` to check crate import instead of strings --- compiler/rustc_resolve/src/diagnostics.rs | 24 ++++------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index af4d7a8eafff3..0b60952ae3c08 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2126,26 +2126,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let source_map = self.r.session.source_map(); // Make sure this is actually crate-relative. - let use_and_crate = import.use_span.with_hi(after_crate_name.lo()); - let is_definitely_crate = - source_map.span_to_snippet(use_and_crate).map_or(false, |s| { - let mut s = s.trim(); - debug!("check_for_module_export_macro: s={s:?}",); - s = s - .split_whitespace() - .rev() - .next() - .expect("split_whitespace always yields at least once"); - debug!("check_for_module_export_macro: s={s:?}",); - if s.ends_with("::") { - s = &s[..s.len() - 2]; - } else { - return false; - } - s = s.trim(); - debug!("check_for_module_export_macro: s={s:?}",); - s != "self" && s != "super" - }); + let is_definitely_crate = import + .module_path + .first() + .map_or(false, |f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super); // Add the import to the start, with a `{` if required. let start_point = source_map.start_point(after_crate_name); From c07a722847497233e6590d62a3d63946409385c3 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 6 Dec 2022 08:44:48 -0700 Subject: [PATCH 4/4] diagnostics: remvoe unnecessary use of `source_map.start_point` --- compiler/rustc_resolve/src/diagnostics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 0b60952ae3c08..8d104aa5cc592 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2153,7 +2153,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } else { // If the root import is module-relative, add the import separately corrections.push(( - source_map.start_point(import.use_span).shrink_to_lo(), + import.use_span.shrink_to_lo(), format!("use {module_name}::{import_snippet};\n"), )); }