Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,15 @@ impl<'ra> ImportData<'ra> {
}
}

/// Returns the first meaningful path segment of this import,
/// skipping synthetic segments like `{{root}}` and `$crate`.
pub(crate) fn first_non_root_segment(&self) -> Option<Symbol> {
self.module_path
.iter()
.find(|seg| seg.ident.name != kw::PathRoot && seg.ident.name != kw::DollarCrate)
.map(|seg| seg.ident.name)
}

pub(crate) fn id(&self) -> Option<NodeId> {
match self.kind {
ImportKind::Single { id, .. }
Expand Down Expand Up @@ -653,6 +662,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {

glob_error |= import.is_glob();

if let Some(name) = import.first_non_root_segment() {
self.failed_import_prefixes.insert(name);
}

if let ImportKind::Single { source, ref decls, .. } = import.kind
&& source.name == kw::SelfLower
// Silence `unresolved import` error if E0429 is already emitted
Expand Down Expand Up @@ -1051,6 +1064,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
if !self.issue_145575_hack_applied {
assert!(import.imported_module.get().is_none());
}
if import.is_nested() {
let module = if let Some(ModuleOrUniformRoot::Module(m)) = module {
m.opt_def_id()
} else {
None
};
return Some(UnresolvedImportError {
span,
label: Some(label),
note: None,
suggestion,
candidates: None,
segment: Some(segment_name),
module,
});
}
self.report_error(
span,
ResolutionError::FailedToResolve {
Expand Down
22 changes: 19 additions & 3 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4424,7 +4424,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {

let Finalize { node_id, path_span, .. } = finalize;
let report_errors = |this: &mut Self, res: Option<Res>| {
if this.should_report_errs() {
if this.should_report_errs_for_path(path) {
let (err, candidates) = this.smart_resolve_report_errors(
path,
None,
Expand Down Expand Up @@ -4558,7 +4558,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {

let def_id = this.parent_scope.module.nearest_parent_mod();

if this.should_report_errs() {
if this.should_report_errs_for_path(path) {
if candidates.is_empty() {
if path.len() == 2
&& let [segment] = prefix_path
Expand Down Expand Up @@ -4668,7 +4668,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {

Err(err) => {
if let Some(err) = report_errors_for_call(self, err) {
self.report_error(err.span, err.node);
if self.should_report_errs_for_path(path) {
self.r.report_error(err.span, err.node);
}
}

PartialRes::new(Res::Err)
Expand Down Expand Up @@ -4717,6 +4719,20 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
&& !self.r.glob_error.is_some()
}

/// Like `should_report_errs`, but also suppresses errors for paths whose
/// first segment matches a known-failed import prefix.
fn should_report_errs_for_path(&self, path: &[Segment]) -> bool {
if !self.should_report_errs() {
return false;
}
if let Some(first) = path.first() {
if self.r.failed_import_prefixes.contains(&first.ident.name) {
return false;
}
}
true
}

// Resolve in alternative namespaces if resolution in the primary namespace fails.
fn resolve_qpath_anywhere(
&mut self,
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,10 @@ pub struct Resolver<'ra, 'tcx> {
glob_error: Option<ErrorGuaranteed> = None,
visibilities_for_hashing: Vec<(LocalDefId, Visibility)> = Vec::new(),
used_imports: FxHashSet<NodeId> = default::fx_hash_set(),
/// First segments of import paths that failed to resolve.
/// Used to suppress redundant resolution errors in late resolver
/// for paths sharing the same unresolved prefix.
failed_import_prefixes: FxHashSet<Symbol>,
maybe_unused_trait_imports: FxIndexSet<LocalDefId>,

/// Privacy errors are delayed until the end in order to deduplicate them.
Expand Down Expand Up @@ -1681,6 +1685,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
extern_module_map: Default::default(),

glob_map: Default::default(),
failed_import_prefixes: FxHashSet::default(),
maybe_unused_trait_imports: Default::default(),

arenas,
Expand Down
6 changes: 1 addition & 5 deletions tests/ui/imports/absolute-paths-in-nested-use-groups.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
#![allow(unused_imports)]

mod foo {}

use foo::{
//~^ ERROR: unresolved import `foo`
::bar,
//~^ ERROR: crate root in paths can only be used in start position
super::bar,
//~^ ERROR: `super` in paths can only be used in start position
self::bar,
//~^ ERROR: `self` in paths can only be used in start position
};

fn main() {}
25 changes: 9 additions & 16 deletions tests/ui/imports/absolute-paths-in-nested-use-groups.stderr
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
error[E0433]: the crate root in paths can only be used in start position
--> $DIR/absolute-paths-in-nested-use-groups.rs:6:5
error[E0432]: unresolved import `foo`
--> $DIR/absolute-paths-in-nested-use-groups.rs:3:5
|
LL | ::bar,
| ^ can only be used in path start position

error[E0433]: `super` in paths can only be used in start position
--> $DIR/absolute-paths-in-nested-use-groups.rs:8:5
LL | use foo::{
| ^^^ use of unresolved module or unlinked crate `foo`
|
LL | super::bar,
| ^^^^^ can only be used in path start position

error[E0433]: `self` in paths can only be used in start position
--> $DIR/absolute-paths-in-nested-use-groups.rs:10:5
help: you might be missing a crate named `foo`, add it to your project and import it in your code
|
LL + extern crate foo;
|
LL | self::bar,
| ^^^^ can only be used in path start position

error: aborting due to 3 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0433`.
For more information about this error, try `rustc --explain E0432`.
4 changes: 2 additions & 2 deletions tests/ui/imports/nested-import-root-symbol-150103.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
// caused by `{{root}}` appearing in diagnostic suggestions

mod A {
use Iuse::{ ::Fish }; //~ ERROR cannot find module or crate `Iuse` in the crate root
use Iuse::{ ::Fish }; //~ ERROR unresolved import `Iuse`
}

mod B {
use A::{::Fish}; //~ ERROR the crate root in paths can only be used in start position
use A::{::Fish}; //~ ERROR unresolved import `A::Fish`
}

fn main() {}
6 changes: 3 additions & 3 deletions tests/ui/imports/nested-import-root-symbol-150103.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0433]: cannot find module or crate `Iuse` in the crate root
error[E0432]: unresolved import `Iuse`
--> $DIR/nested-import-root-symbol-150103.rs:6:9
|
LL | use Iuse::{ ::Fish };
Expand All @@ -9,12 +9,12 @@ help: you might be missing a crate named `Iuse`, add it to your project and impo
LL + extern crate Iuse;
|

error[E0433]: the crate root in paths can only be used in start position
error[E0432]: unresolved import `A::Fish`
--> $DIR/nested-import-root-symbol-150103.rs:10:13
|
LL | use A::{::Fish};
| ^ can only be used in path start position

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0433`.
For more information about this error, try `rustc --explain E0432`.
8 changes: 8 additions & 0 deletions tests/ui/imports/redundant-import-errors-nested.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Issue #153156: Too many errors for missing crate for nested imports and later uses

use foo::{bar, baz::bat};
//~^ ERROR unresolved import `foo`

pub fn main() {
foo::qux();
}
14 changes: 14 additions & 0 deletions tests/ui/imports/redundant-import-errors-nested.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0432]: unresolved import `foo`
--> $DIR/redundant-import-errors-nested.rs:3:5
|
LL | use foo::{bar, baz::bat};
| ^^^ use of unresolved module or unlinked crate `foo`
|
help: you might be missing a crate named `foo`, add it to your project and import it in your code
|
LL + extern crate foo;
|

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0432`.
1 change: 0 additions & 1 deletion tests/ui/traits/const-traits/issue-102156.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use core::convert::{From, TryFrom};
//~^ ERROR
//~| ERROR

use std::pin::Pin;
use std::alloc::Allocator;
Expand Down
19 changes: 3 additions & 16 deletions tests/ui/traits/const-traits/issue-102156.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0433]: cannot find `core` in the crate root
error[E0432]: unresolved import `core`
--> $DIR/issue-102156.rs:5:5
|
LL | use core::convert::{From, TryFrom};
Expand All @@ -10,19 +10,6 @@ LL - use core::convert::{From, TryFrom};
LL + use std::convert::{From, TryFrom};
|

error[E0433]: cannot find `core` in the crate root
--> $DIR/issue-102156.rs:5:5
|
LL | use core::convert::{From, TryFrom};
| ^^^^ you might be missing crate `core`
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: try using `std` instead of `core`
|
LL - use core::convert::{From, TryFrom};
LL + use std::convert::{From, TryFrom};
|

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0433`.
For more information about this error, try `rustc --explain E0432`.
31 changes: 1 addition & 30 deletions tests/ui/use/use-path-segment-kw.e2015.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -1027,17 +1027,6 @@ LL | macro_dollar_crate!();
|
= note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0433]: `$crate` in paths can only be used in start position
--> $DIR/use-path-segment-kw.rs:20:27
|
LL | type A3 = foobar::$crate;
| ^^^^^^ can only be used in path start position
...
LL | macro_dollar_crate!();
| --------------------- in this macro invocation
|
= note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0433]: `$crate` in paths can only be used in start position
--> $DIR/use-path-segment-kw.rs:26:26
|
Expand Down Expand Up @@ -1121,12 +1110,6 @@ error[E0433]: global paths cannot start with `crate`
LL | type B2 = ::crate;
| ^^^^^ cannot start with this

error[E0433]: `crate` in paths can only be used in start position
--> $DIR/use-path-segment-kw.rs:106:27
|
LL | type B3 = foobar::crate;
| ^^^^^ can only be used in path start position

error[E0433]: `crate` in paths can only be used in start position
--> $DIR/use-path-segment-kw.rs:112:26
|
Expand All @@ -1151,12 +1134,6 @@ error[E0433]: global paths cannot start with `super`
LL | type C2 = ::super;
| ^^^^^ cannot start with this

error[E0433]: `super` in paths can only be used in start position
--> $DIR/use-path-segment-kw.rs:144:27
|
LL | type C3 = foobar::super;
| ^^^^^ can only be used in path start position

error[E0433]: `super` in paths can only be used in start position
--> $DIR/use-path-segment-kw.rs:150:26
|
Expand All @@ -1169,12 +1146,6 @@ error[E0433]: global paths cannot start with `self`
LL | type D2 = ::self;
| ^^^^ cannot start with this

error[E0433]: `self` in paths can only be used in start position
--> $DIR/use-path-segment-kw.rs:186:27
|
LL | type D3 = foobar::self;
| ^^^^ can only be used in path start position

error[E0433]: `self` in paths can only be used in start position
--> $DIR/use-path-segment-kw.rs:194:26
|
Expand All @@ -1193,7 +1164,7 @@ error[E0433]: `self` in paths can only be used in start position
LL | type D6 = self::self;
| ^^^^ can only be used in path start position

error: aborting due to 129 previous errors
error: aborting due to 125 previous errors

Some errors have detailed explanations: E0429, E0432, E0433, E0573.
For more information about an error, try `rustc --explain E0429`.
8 changes: 4 additions & 4 deletions tests/ui/use/use-path-segment-kw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ macro_rules! macro_dollar_crate {
use ::{$crate}; //~ ERROR `$crate` in paths can only be used in start position
use ::{$crate as _nested_dollar_crate2}; //~ ERROR `$crate` in paths can only be used in start position

type A3 = foobar::$crate; //~ ERROR `$crate` in paths can only be used in start position
type A3 = foobar::$crate; //[e2018]~ ERROR `$crate` in paths can only be used in start position
use foobar::$crate; //~ ERROR `$crate` in paths can only be used in start position
use foobar::$crate as _dollar_crate3; //~ ERROR `$crate` in paths can only be used in start position
use foobar::{$crate}; //~ ERROR `$crate` in paths can only be used in start position
Expand Down Expand Up @@ -103,7 +103,7 @@ mod foo {
use ::{crate}; //~ ERROR `crate` in paths can only be used in start position
use ::{crate as _nested_crate2}; //~ ERROR `crate` in paths can only be used in start position

type B3 = foobar::crate; //~ ERROR `crate` in paths can only be used in start position
type B3 = foobar::crate; //[e2018]~ ERROR `crate` in paths can only be used in start position
use foobar::crate; //~ ERROR `crate` in paths can only be used in start position
use foobar::crate as _crate3; //~ ERROR `crate` in paths can only be used in start position
use foobar::{crate}; //~ ERROR `crate` in paths can only be used in start position
Expand Down Expand Up @@ -141,7 +141,7 @@ mod foo {
use ::{super}; //~ ERROR `super` in paths can only be used in start position, after `self`, or after another `super`
use ::{super as _nested_super2}; //~ ERROR `super` in paths can only be used in start position, after `self`, or after another `super`

type C3 = foobar::super; //~ ERROR `super` in paths can only be used in start position
type C3 = foobar::super; //[e2018]~ ERROR `super` in paths can only be used in start position
use foobar::super; //~ ERROR `super` in paths can only be used in start position, after `self`, or after another `super`
use foobar::super as _super3; //~ ERROR `super` in paths can only be used in start position, after `self`, or after another `super`
use foobar::{super}; //~ ERROR `super` in paths can only be used in start position, after `self`, or after another `super`
Expand Down Expand Up @@ -183,7 +183,7 @@ mod foo {
//[e2015]~^ ERROR imports need to be explicitly named
pub use ::{self as _nested_self2}; //[e2018]~ ERROR extern prelude cannot be imported

type D3 = foobar::self; //~ ERROR `self` in paths can only be used in start position
type D3 = foobar::self; //[e2018]~ ERROR `self` in paths can only be used in start position
pub use foobar::qux::self; //~ ERROR `self` imports are only allowed within a { } list
//[e2015]~^ ERROR unresolved import `foobar`
pub use foobar::self as _self3; //~ ERROR `self` imports are only allowed within a { } list
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/use/use-super-global-path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ struct Z;

mod foo {
use ::super::{S, Z};
//~^ ERROR: global paths cannot start with `super`
//~| ERROR: global paths cannot start with `super`
//~^ ERROR: unresolved import `super`

pub fn g() {
use ::super::main; //~ ERROR: global paths cannot start with `super`
Expand Down
Loading
Loading