Skip to content

Commit ac89d2b

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 7116a50 commit ac89d2b

13 files changed

Lines changed: 85 additions & 88 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
@@ -4424,7 +4424,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
44244424

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

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

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

46694669
Err(err) => {
46704670
if let Some(err) = report_errors_for_call(self, err) {
4671-
self.report_error(err.span, err.node);
4671+
if self.should_report_errs_for_path(path) {
4672+
self.r.report_error(err.span, err.node);
4673+
}
46724674
}
46734675

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

4722+
/// Like `should_report_errs`, but also suppresses errors for paths whose
4723+
/// first segment matches a known-failed import prefix.
4724+
fn should_report_errs_for_path(&self, path: &[Segment]) -> bool {
4725+
if !self.should_report_errs() {
4726+
return false;
4727+
}
4728+
if let Some(first) = path.first() {
4729+
if self.r.failed_import_prefixes.contains(&first.ident.name) {
4730+
return false;
4731+
}
4732+
}
4733+
true
4734+
}
4735+
47204736
// Resolve in alternative namespaces if resolution in the primary namespace fails.
47214737
fn resolve_qpath_anywhere(
47224738
&mut self,

compiler/rustc_resolve/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,10 @@ pub struct Resolver<'ra, 'tcx> {
12421242
glob_error: Option<ErrorGuaranteed> = None,
12431243
visibilities_for_hashing: Vec<(LocalDefId, Visibility)> = Vec::new(),
12441244
used_imports: FxHashSet<NodeId> = default::fx_hash_set(),
1245+
/// First segments of import paths that failed to resolve.
1246+
/// Used to suppress redundant resolution errors in late resolver
1247+
/// for paths sharing the same unresolved prefix.
1248+
failed_import_prefixes: FxHashSet<Symbol>,
12451249
maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
12461250

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

16831687
glob_map: Default::default(),
1688+
glob_error: None,
1689+
failed_import_prefixes: FxHashSet::default(),
1690+
used_imports: FxHashSet::default(),
1691+
visibilities_for_hashing: Default::default(),
16841692
maybe_unused_trait_imports: Default::default(),
16851693

16861694
arenas,
Lines changed: 0 additions & 4 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::{
64
::bar,
75
//~^ 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`.
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;
Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0433]: cannot find `core` in the crate root
1+
error[E0432]: unresolved import `core`
22
--> $DIR/issue-102156.rs:5:5
33
|
44
LL | use core::convert::{From, TryFrom};
@@ -10,19 +10,6 @@ LL - use core::convert::{From, TryFrom};
1010
LL + use std::convert::{From, TryFrom};
1111
|
1212

13-
error[E0433]: cannot find `core` in the crate root
14-
--> $DIR/issue-102156.rs:5:5
15-
|
16-
LL | use core::convert::{From, TryFrom};
17-
| ^^^^ you might be missing crate `core`
18-
|
19-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
20-
help: try using `std` instead of `core`
21-
|
22-
LL - use core::convert::{From, TryFrom};
23-
LL + use std::convert::{From, TryFrom};
24-
|
25-
26-
error: aborting due to 2 previous errors
13+
error: aborting due to 1 previous error
2714

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

0 commit comments

Comments
 (0)