diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index c4a0cde2837a0..9fbc73618ce80 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -629,6 +629,35 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { // `true` for `...::{self [as target]}` imports, `false` otherwise. let type_ns_only = nested && source.ident.name == kw::SelfLower; + if source.ident.name == kw::SelfLower + && let Some(parent) = module_path.pop() + { + // Suggest `use prefix::{self};` for `use prefix::self;` + if !type_ns_only + && (parent.ident.name != kw::PathRoot + || self.r.path_root_is_crate_root(parent.ident)) + { + let span_with_rename = match rename { + Some(rename) => source.ident.span.to(rename.span), + None => source.ident.span, + }; + + self.r.report_error( + parent.ident.span.shrink_to_hi().to(source.ident.span), + ResolutionError::SelfImportsOnlyAllowedWithin { + root: parent.ident.name == kw::PathRoot, + span_with_rename, + }, + ); + } + + let self_span = source.ident.span; + source = parent; + if rename.is_none() { + ident = Ident::new(source.ident.name, self_span); + } + } + match source.ident.name { kw::DollarCrate => { if !module_path.is_empty() { @@ -664,45 +693,14 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { return; } } - kw::SelfLower => { - if let Some(parent) = module_path.pop() { - // Suggest `use prefix::{self};` for `use prefix::self;` - if !type_ns_only - && (parent.ident.name != kw::PathRoot - || self.r.path_root_is_crate_root(parent.ident)) - { - let span_with_rename = match rename { - Some(rename) => source.ident.span.to(rename.span), - None => source.ident.span, - }; - - self.r.report_error( - parent.ident.span.shrink_to_hi().to(source.ident.span), - ResolutionError::SelfImportsOnlyAllowedWithin { - root: parent.ident.name == kw::PathRoot, - span_with_rename, - }, - ); - } - - let self_span = source.ident.span; - source = parent; - if rename.is_none() { - ident = Ident::new(source.ident.name, self_span); - } - } + // Deny `use ::{self};` after edition 2015 + kw::PathRoot if !self.r.path_root_is_crate_root(source.ident) => { + self.r.dcx().span_err(use_tree.span, "extern prelude cannot be imported"); + return; } _ => {} } - // Deny `use ::{self};` after edition 2015 - if source.ident.name == kw::PathRoot - && !self.r.path_root_is_crate_root(source.ident) - { - self.r.dcx().span_err(use_tree.span, "extern prelude cannot be imported"); - return; - } - // Deny importing path-kw without renaming if rename.is_none() && ident.is_path_segment_keyword() { let ident = use_tree.ident(); diff --git a/tests/ui/use/use-super-in-middle.rs b/tests/ui/use/use-super-in-middle.rs new file mode 100644 index 0000000000000..be9f3675c323f --- /dev/null +++ b/tests/ui/use/use-super-in-middle.rs @@ -0,0 +1,14 @@ +pub mod x { + pub use crate::x::super::{self as crate1}; //~ ERROR `super` in paths can only be used in start position + pub use crate::x::self::super::{self as crate2}; //~ ERROR `super` in paths can only be used in start position + + pub fn foo() {} +} + +fn main() { + x::crate1::x::foo(); //~ ERROR cannot find `crate1` in `x` + x::crate2::x::foo(); //~ ERROR cannot find `crate2` in `x` + + crate::x::super::x::foo(); //~ ERROR `super` in paths can only be used in start position + crate::x::self::super::x::foo(); //~ ERROR `self` in paths can only be used in start position +} diff --git a/tests/ui/use/use-super-in-middle.stderr b/tests/ui/use/use-super-in-middle.stderr new file mode 100644 index 0000000000000..276b1274f6a89 --- /dev/null +++ b/tests/ui/use/use-super-in-middle.stderr @@ -0,0 +1,39 @@ +error: `super` in paths can only be used in start position, after `self`, or after another `super` + --> $DIR/use-super-in-middle.rs:2:23 + | +LL | pub use crate::x::super::{self as crate1}; + | ^^^^^ + +error: `super` in paths can only be used in start position, after `self`, or after another `super` + --> $DIR/use-super-in-middle.rs:3:29 + | +LL | pub use crate::x::self::super::{self as crate2}; + | ^^^^^ + +error[E0433]: cannot find `crate1` in `x` + --> $DIR/use-super-in-middle.rs:9:8 + | +LL | x::crate1::x::foo(); + | ^^^^^^ could not find `crate1` in `x` + +error[E0433]: cannot find `crate2` in `x` + --> $DIR/use-super-in-middle.rs:10:8 + | +LL | x::crate2::x::foo(); + | ^^^^^^ could not find `crate2` in `x` + +error[E0433]: `super` in paths can only be used in start position + --> $DIR/use-super-in-middle.rs:12:15 + | +LL | crate::x::super::x::foo(); + | ^^^^^ can only be used in path start position + +error[E0433]: `self` in paths can only be used in start position + --> $DIR/use-super-in-middle.rs:13:15 + | +LL | crate::x::self::super::x::foo(); + | ^^^^ can only be used in path start position + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0433`.