Skip to content

Commit ea4f0fd

Browse files
committed
Suppress redundant E0433 for paths matching failed import prefixes
Track first segments of failed imports and skip late resolution errors for paths sharing the same prefix. This avoids redundant E0433 after an E0432 has already been reported for the same missing module, without suppressing unrelated diagnostics.
1 parent 64589e9 commit ea4f0fd

15 files changed

Lines changed: 90 additions & 96 deletions

compiler/rustc_resolve/src/imports.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,15 @@ impl<'ra> ImportData<'ra> {
217217
}
218218
}
219219

220+
/// Returns the first meaningful path segment of this import,
221+
/// skipping synthetic segments like `{{root}}` and `$crate`.
222+
pub(crate) fn first_non_root_segment(&self) -> Option<Symbol> {
223+
self.module_path
224+
.iter()
225+
.find(|seg| seg.ident.name != kw::PathRoot && seg.ident.name != kw::DollarCrate)
226+
.map(|seg| seg.ident.name)
227+
}
228+
220229
pub(crate) fn id(&self) -> Option<NodeId> {
221230
match self.kind {
222231
ImportKind::Single { id, .. }
@@ -653,6 +662,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
653662

654663
glob_error |= import.is_glob();
655664

665+
if let Some(name) = import.first_non_root_segment() {
666+
self.failed_import_prefixes.insert(name);
667+
}
668+
656669
if let ImportKind::Single { source, ref decls, .. } = import.kind
657670
&& source.name == kw::SelfLower
658671
// Silence `unresolved import` error if E0429 is already emitted

compiler/rustc_resolve/src/late.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4462,7 +4462,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
44624462

44634463
let Finalize { node_id, path_span, .. } = finalize;
44644464
let report_errors = |this: &mut Self, res: Option<Res>| {
4465-
if this.should_report_errs() {
4465+
if this.should_report_errs_for_path(path) {
44664466
let (mut err, candidates) = this.smart_resolve_report_errors(
44674467
path,
44684468
None,
@@ -4605,7 +4605,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46054605

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

4608-
if this.should_report_errs() {
4608+
if this.should_report_errs_for_path(path) {
46094609
if candidates.is_empty() {
46104610
if path.len() == 2
46114611
&& let [segment] = prefix_path
@@ -4715,7 +4715,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
47154715

47164716
Err(err) => {
47174717
if let Some(err) = report_errors_for_call(self, err) {
4718-
self.report_error(err.span, err.node);
4718+
if self.should_report_errs_for_path(path) {
4719+
self.r.report_error(err.span, err.node);
4720+
}
47194721
}
47204722

47214723
PartialRes::new(Res::Err)
@@ -4764,6 +4766,20 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
47644766
&& !self.r.glob_error.is_some()
47654767
}
47664768

4769+
/// Like `should_report_errs`, but also suppresses errors for paths whose
4770+
/// first segment matches a known-failed import prefix.
4771+
fn should_report_errs_for_path(&self, path: &[Segment]) -> bool {
4772+
if !self.should_report_errs() {
4773+
return false;
4774+
}
4775+
if let Some(first) = path.first() {
4776+
if self.r.failed_import_prefixes.contains(&first.ident.name) {
4777+
return false;
4778+
}
4779+
}
4780+
true
4781+
}
4782+
47674783
// Resolve in alternative namespaces if resolution in the primary namespace fails.
47684784
fn resolve_qpath_anywhere(
47694785
&mut self,

compiler/rustc_resolve/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,10 @@ pub struct Resolver<'ra, 'tcx> {
12671267
glob_error: Option<ErrorGuaranteed> = None,
12681268
visibilities_for_hashing: Vec<(LocalDefId, Visibility)> = Vec::new(),
12691269
used_imports: FxHashSet<NodeId> = default::fx_hash_set(),
1270+
/// First segments of import paths that failed to resolve.
1271+
/// Used to suppress redundant resolution errors in late resolver
1272+
/// for paths sharing the same unresolved prefix.
1273+
failed_import_prefixes: FxHashSet<Symbol>,
12701274
maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
12711275

12721276
/// Privacy errors are delayed until the end in order to deduplicate them.
@@ -1682,6 +1686,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
16821686
extern_module_map: Default::default(),
16831687

16841688
glob_map: Default::default(),
1689+
failed_import_prefixes: FxHashSet::default(),
16851690
maybe_unused_trait_imports: Default::default(),
16861691

16871692
arenas,
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
#![allow(unused_imports)]
22

3-
mod foo {}
4-
53
use foo::{
4+
//~^ ERROR: unresolved import `foo`
65
::bar,
7-
//~^ ERROR: crate root in paths can only be used in start position
86
super::bar,
9-
//~^ ERROR: `super` in paths can only be used in start position
107
self::bar,
11-
//~^ ERROR: `self` in paths can only be used in start position
128
};
139

1410
fn main() {}
Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
1-
error[E0433]: the crate root in paths can only be used in start position
2-
--> $DIR/absolute-paths-in-nested-use-groups.rs:6:5
1+
error[E0432]: unresolved import `foo`
2+
--> $DIR/absolute-paths-in-nested-use-groups.rs:3:5
33
|
4-
LL | ::bar,
5-
| ^ can only be used in path start position
6-
7-
error[E0433]: `super` in paths can only be used in start position
8-
--> $DIR/absolute-paths-in-nested-use-groups.rs:8:5
4+
LL | use foo::{
5+
| ^^^ use of unresolved module or unlinked crate `foo`
96
|
10-
LL | super::bar,
11-
| ^^^^^ can only be used in path start position
12-
13-
error[E0433]: `self` in paths can only be used in start position
14-
--> $DIR/absolute-paths-in-nested-use-groups.rs:10:5
7+
help: you might be missing a crate named `foo`, add it to your project and import it in your code
8+
|
9+
LL + extern crate foo;
1510
|
16-
LL | self::bar,
17-
| ^^^^ can only be used in path start position
1811

19-
error: aborting due to 3 previous errors
12+
error: aborting due to 1 previous error
2013

21-
For more information about this error, try `rustc --explain E0433`.
14+
For more information about this error, try `rustc --explain E0432`.

tests/ui/imports/nested-import-root-symbol-150103.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
// caused by `{{root}}` appearing in diagnostic suggestions
44

55
mod A {
6-
use Iuse::{ ::Fish }; //~ ERROR cannot find module or crate `Iuse` in the crate root
6+
use Iuse::{ ::Fish }; //~ ERROR unresolved import `Iuse`
77
}
88

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

1313
fn main() {}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0433]: cannot find module or crate `Iuse` in the crate root
1+
error[E0432]: unresolved import `Iuse`
22
--> $DIR/nested-import-root-symbol-150103.rs:6:9
33
|
44
LL | use Iuse::{ ::Fish };
@@ -9,12 +9,12 @@ help: you might be missing a crate named `Iuse`, add it to your project and impo
99
LL + extern crate Iuse;
1010
|
1111

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

1818
error: aborting due to 2 previous errors
1919

20-
For more information about this error, try `rustc --explain E0433`.
20+
For more information about this error, try `rustc --explain E0432`.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Issue #153156: Too many errors for missing crate for nested imports and later uses
2+
3+
use foo::{bar, baz::bat};
4+
//~^ ERROR unresolved import `foo`
5+
6+
pub fn main() {
7+
foo::qux();
8+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0432]: unresolved import `foo`
2+
--> $DIR/redundant-import-errors-nested.rs:3:5
3+
|
4+
LL | use foo::{bar, baz::bat};
5+
| ^^^ use of unresolved module or unlinked crate `foo`
6+
|
7+
help: you might be missing a crate named `foo`, add it to your project and import it in your code
8+
|
9+
LL + extern crate foo;
10+
|
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0432`.

tests/ui/traits/const-traits/issue-102156.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use core::convert::{From, TryFrom};
66
//~^ ERROR
7-
//~| ERROR
87

98
use std::pin::Pin;
109
use std::alloc::Allocator;

0 commit comments

Comments
 (0)