diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index ce41dd86a48be..24e679a6323c1 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -3572,10 +3572,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } else { // If the root import is module-relative, add the import separately - corrections.push(( - import.use_span.shrink_to_lo(), - format!("use {module_name}::{import_snippet};\n"), - )); + if let Ok(vis) = source_map.span_to_snippet(import.vis_span) + && let Some(indentation) = source_map.indentation_before(import.use_span) + { + let vis = if vis.trim().is_empty() { String::new() } else { format!("{vis} ") }; + corrections.push(( + import.use_span.shrink_to_lo(), + format!("{vis}use {module_name}::{import_snippet};\n{indentation}"), + )); + } } } diff --git a/tests/ui/imports/issue-99695-b.fixed b/tests/ui/imports/issue-99695-b.fixed index ae63b0c4627c5..2804be27bbb2a 100644 --- a/tests/ui/imports/issue-99695-b.fixed +++ b/tests/ui/imports/issue-99695-b.fixed @@ -11,8 +11,8 @@ mod m { pub struct other_item; } - use crate::nu; -pub use self::p::{other_item as _}; + pub use crate::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 } diff --git a/tests/ui/imports/issue-99695-b.stderr b/tests/ui/imports/issue-99695-b.stderr index ad752d5c45a7e..5352c26a06ae1 100644 --- a/tests/ui/imports/issue-99695-b.stderr +++ b/tests/ui/imports/issue-99695-b.stderr @@ -7,8 +7,8 @@ LL | pub use self::p::{nu, other_item as _}; = 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 crate::nu; -LL ~ pub use self::p::{other_item as _}; +LL ~ pub use crate::nu; +LL ~ pub use self::p::{other_item as _}; | error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-99695.edition_2015.fixed b/tests/ui/imports/issue-99695.edition_2015.fixed index 798acfd587467..58018baffd7b9 100644 --- a/tests/ui/imports/issue-99695.edition_2015.fixed +++ b/tests/ui/imports/issue-99695.edition_2015.fixed @@ -12,8 +12,8 @@ mod m { pub struct other_item; - use crate::nu; -pub use self::{other_item as _}; + pub use crate::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 } diff --git a/tests/ui/imports/issue-99695.edition_2015.stderr b/tests/ui/imports/issue-99695.edition_2015.stderr index 4ef8e6426fb29..ad24b406c34ca 100644 --- a/tests/ui/imports/issue-99695.edition_2015.stderr +++ b/tests/ui/imports/issue-99695.edition_2015.stderr @@ -7,8 +7,8 @@ LL | pub use self::{nu, other_item as _}; = 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 crate::nu; -LL ~ pub use self::{other_item as _}; +LL ~ pub use crate::nu; +LL ~ pub use self::{other_item as _}; | error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-99695.edition_2018.fixed b/tests/ui/imports/issue-99695.edition_2018.fixed index 798acfd587467..58018baffd7b9 100644 --- a/tests/ui/imports/issue-99695.edition_2018.fixed +++ b/tests/ui/imports/issue-99695.edition_2018.fixed @@ -12,8 +12,8 @@ mod m { pub struct other_item; - use crate::nu; -pub use self::{other_item as _}; + pub use crate::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 } diff --git a/tests/ui/imports/issue-99695.edition_2018.stderr b/tests/ui/imports/issue-99695.edition_2018.stderr index 4ef8e6426fb29..ad24b406c34ca 100644 --- a/tests/ui/imports/issue-99695.edition_2018.stderr +++ b/tests/ui/imports/issue-99695.edition_2018.stderr @@ -7,8 +7,8 @@ LL | pub use self::{nu, other_item as _}; = 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 crate::nu; -LL ~ pub use self::{other_item as _}; +LL ~ pub use crate::nu; +LL ~ pub use self::{other_item as _}; | error: aborting due to 1 previous error diff --git a/tests/ui/imports/macro-export-nested-import-visibility-issue-141134.fixed b/tests/ui/imports/macro-export-nested-import-visibility-issue-141134.fixed new file mode 100644 index 0000000000000..0311defd9e83f --- /dev/null +++ b/tests/ui/imports/macro-export-nested-import-visibility-issue-141134.fixed @@ -0,0 +1,79 @@ +//@ run-rustfix +//@ edition: 2021 + +// Nested macro import suggestions should preserve the original `use` visibility. + +#![allow(unused)] + +mod a { + #[macro_export] + macro_rules! m_pub { + () => {}; + } + #[macro_export] + macro_rules! m_crate { + () => {}; + } + #[macro_export] + macro_rules! m_in { + () => {}; + } + #[macro_export] + macro_rules! m_super { + () => {}; + } + #[macro_export] + macro_rules! m_self { + () => {}; + } + #[macro_export] + macro_rules! m_private { + () => {}; + } + + pub struct S; + + mod b0 { + pub use crate::m_pub; + pub use super::{S as PubS}; + //~^ ERROR unresolved import `super::m_pub` + //~| HELP a macro with this name exists at the root of the crate + } + + mod b1 { + pub(crate) use crate::m_crate; + pub(crate) use super::{S as CrateS}; + //~^ ERROR unresolved import `super::m_crate` + //~| HELP a macro with this name exists at the root of the crate + } + + mod b2 { + pub(in crate::a) use crate::m_in; + pub(in crate::a) use super::{S as InS}; + //~^ ERROR unresolved import `super::m_in` + //~| HELP a macro with this name exists at the root of the crate + } + + mod b3 { + pub(super) use crate::m_super; + pub(super) use super::{S as SuperS}; + //~^ ERROR unresolved import `super::m_super` + //~| HELP a macro with this name exists at the root of the crate + } + + mod b4 { + pub(self) use crate::m_self; + pub(self) use super::{S as SelfS}; + //~^ ERROR unresolved import `super::m_self` + //~| HELP a macro with this name exists at the root of the crate + } + + mod b5 { + use crate::m_private; + use super::{S as PrivateS}; + //~^ ERROR unresolved import `super::m_private` + //~| HELP a macro with this name exists at the root of the crate + } +} + +fn main() {} diff --git a/tests/ui/imports/macro-export-nested-import-visibility-issue-141134.rs b/tests/ui/imports/macro-export-nested-import-visibility-issue-141134.rs new file mode 100644 index 0000000000000..5be2ba6ff85df --- /dev/null +++ b/tests/ui/imports/macro-export-nested-import-visibility-issue-141134.rs @@ -0,0 +1,73 @@ +//@ run-rustfix +//@ edition: 2021 + +// Nested macro import suggestions should preserve the original `use` visibility. + +#![allow(unused)] + +mod a { + #[macro_export] + macro_rules! m_pub { + () => {}; + } + #[macro_export] + macro_rules! m_crate { + () => {}; + } + #[macro_export] + macro_rules! m_in { + () => {}; + } + #[macro_export] + macro_rules! m_super { + () => {}; + } + #[macro_export] + macro_rules! m_self { + () => {}; + } + #[macro_export] + macro_rules! m_private { + () => {}; + } + + pub struct S; + + mod b0 { + pub use super::{m_pub, S as PubS}; + //~^ ERROR unresolved import `super::m_pub` + //~| HELP a macro with this name exists at the root of the crate + } + + mod b1 { + pub(crate) use super::{m_crate, S as CrateS}; + //~^ ERROR unresolved import `super::m_crate` + //~| HELP a macro with this name exists at the root of the crate + } + + mod b2 { + pub(in crate::a) use super::{m_in, S as InS}; + //~^ ERROR unresolved import `super::m_in` + //~| HELP a macro with this name exists at the root of the crate + } + + mod b3 { + pub(super) use super::{m_super, S as SuperS}; + //~^ ERROR unresolved import `super::m_super` + //~| HELP a macro with this name exists at the root of the crate + } + + mod b4 { + pub(self) use super::{m_self, S as SelfS}; + //~^ ERROR unresolved import `super::m_self` + //~| HELP a macro with this name exists at the root of the crate + } + + mod b5 { + use super::{m_private, S as PrivateS}; + //~^ ERROR unresolved import `super::m_private` + //~| HELP a macro with this name exists at the root of the crate + } +} + +fn main() {} diff --git a/tests/ui/imports/macro-export-nested-import-visibility-issue-141134.stderr b/tests/ui/imports/macro-export-nested-import-visibility-issue-141134.stderr new file mode 100644 index 0000000000000..f1cf7e6aa56a0 --- /dev/null +++ b/tests/ui/imports/macro-export-nested-import-visibility-issue-141134.stderr @@ -0,0 +1,81 @@ +error[E0432]: unresolved import `super::m_pub` + --> $DIR/macro-export-nested-import-visibility-issue-141134.rs:37:25 + | +LL | pub use super::{m_pub, S as PubS}; + | ^^^^^ no `m_pub` in `a` + | + = 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 ~ pub use crate::m_pub; +LL ~ pub use super::{S as PubS}; + | + +error[E0432]: unresolved import `super::m_crate` + --> $DIR/macro-export-nested-import-visibility-issue-141134.rs:43:32 + | +LL | pub(crate) use super::{m_crate, S as CrateS}; + | ^^^^^^^ no `m_crate` in `a` + | + = 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 ~ pub(crate) use crate::m_crate; +LL ~ pub(crate) use super::{S as CrateS}; + | + +error[E0432]: unresolved import `super::m_in` + --> $DIR/macro-export-nested-import-visibility-issue-141134.rs:49:38 + | +LL | pub(in crate::a) use super::{m_in, S as InS}; + | ^^^^ no `m_in` in `a` + | + = 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 ~ pub(in crate::a) use crate::m_in; +LL ~ pub(in crate::a) use super::{S as InS}; + | + +error[E0432]: unresolved import `super::m_super` + --> $DIR/macro-export-nested-import-visibility-issue-141134.rs:55:32 + | +LL | pub(super) use super::{m_super, S as SuperS}; + | ^^^^^^^ no `m_super` in `a` + | + = 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 ~ pub(super) use crate::m_super; +LL ~ pub(super) use super::{S as SuperS}; + | + +error[E0432]: unresolved import `super::m_self` + --> $DIR/macro-export-nested-import-visibility-issue-141134.rs:61:31 + | +LL | pub(self) use super::{m_self, S as SelfS}; + | ^^^^^^ no `m_self` in `a` + | + = 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 ~ pub(self) use crate::m_self; +LL ~ pub(self) use super::{S as SelfS}; + | + +error[E0432]: unresolved import `super::m_private` + --> $DIR/macro-export-nested-import-visibility-issue-141134.rs:67:21 + | +LL | use super::{m_private, S as PrivateS}; + | ^^^^^^^^^ no `m_private` in `a` + | + = 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 crate::m_private; +LL ~ use super::{S as PrivateS}; + | + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0432`.