Skip to content

Commit 09195d3

Browse files
committed
resolve: Create dummy bindings for all unresolved imports
1 parent 18f32b7 commit 09195d3

File tree

5 files changed

+48
-45
lines changed

5 files changed

+48
-45
lines changed

compiler/rustc_resolve/src/imports.rs

+28-30
Original file line numberDiff line numberDiff line change
@@ -583,18 +583,23 @@ impl<'a> Resolver<'a> {
583583
t
584584
}
585585

586-
// Define a "dummy" resolution containing a Res::Err as a placeholder for a
587-
// failed resolution
586+
// Define a dummy resolution containing a `Res::Err` as a placeholder for a failed resolution,
587+
// also mark such failed imports as used to avoid duplicate diagnostics.
588588
fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
589-
if let ImportKind::Single { target, .. } = import.kind {
589+
if let ImportKind::Single { target, ref target_bindings, .. } = import.kind {
590+
if target_bindings.iter().any(|binding| binding.get().is_some()) {
591+
return; // Has resolution, do not create the dummy binding
592+
}
590593
let dummy_binding = self.dummy_binding;
591594
let dummy_binding = self.import(dummy_binding, import);
592595
self.per_ns(|this, ns| {
593596
let key = this.new_key(target, ns);
594597
let _ = this.try_define(import.parent_scope.module, key, dummy_binding);
595598
});
596-
// Consider erroneous imports used to avoid duplicate diagnostics.
597599
self.record_use(target, dummy_binding, false);
600+
} else if import.imported_module.get().is_none() {
601+
import.used.set(true);
602+
self.used_imports.insert(import.id);
598603
}
599604
}
600605
}
@@ -659,7 +664,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
659664
.map(|i| (false, i))
660665
.chain(indeterminate_imports.into_iter().map(|i| (true, i)))
661666
{
662-
if let Some(err) = self.finalize_import(import) {
667+
let unresolved_import_error = self.finalize_import(import);
668+
669+
// If this import is unresolved then create a dummy import
670+
// resolution for it so that later resolve stages won't complain.
671+
self.r.import_dummy_binding(import);
672+
673+
if let Some(err) = unresolved_import_error {
663674
if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
664675
if source.name == kw::SelfLower {
665676
// Silence `unresolved import` error if E0429 is already emitted
@@ -669,9 +680,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
669680
}
670681
}
671682

672-
// If the error is a single failed import then create a "fake" import
673-
// resolution for it so that later resolve stages won't complain.
674-
self.r.import_dummy_binding(import);
675683
if prev_root_id.as_u32() != 0
676684
&& prev_root_id.as_u32() != import.root_id.as_u32()
677685
&& !errors.is_empty()
@@ -691,8 +699,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
691699
prev_root_id = import.root_id;
692700
}
693701
} else if is_indeterminate {
694-
// Consider erroneous imports used to avoid duplicate diagnostics.
695-
self.r.used_imports.insert(import.id);
696702
let path = import_path_to_string(
697703
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
698704
&import.kind,
@@ -824,26 +830,23 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
824830
Err(Undetermined) => indeterminate = true,
825831
// Don't update the resolution, because it was never added.
826832
Err(Determined) if target.name == kw::Underscore => {}
827-
Err(Determined) => {
833+
Ok(binding) if binding.is_importable() => {
834+
let imported_binding = this.import(binding, import);
835+
target_bindings[ns].set(Some(imported_binding));
836+
this.define(parent, target, ns, imported_binding);
837+
}
838+
source_binding @ (Ok(..) | Err(Determined)) => {
839+
if source_binding.is_ok() {
840+
let msg = format!("`{}` is not directly importable", target);
841+
struct_span_err!(this.session, import.span, E0253, "{}", &msg)
842+
.span_label(import.span, "cannot be imported directly")
843+
.emit();
844+
}
828845
let key = this.new_key(target, ns);
829846
this.update_resolution(parent, key, |_, resolution| {
830847
resolution.single_imports.remove(&Interned::new_unchecked(import));
831848
});
832849
}
833-
Ok(binding) if !binding.is_importable() => {
834-
let msg = format!("`{}` is not directly importable", target);
835-
struct_span_err!(this.session, import.span, E0253, "{}", &msg)
836-
.span_label(import.span, "cannot be imported directly")
837-
.emit();
838-
// Do not import this illegal binding. Import a dummy binding and pretend
839-
// everything is fine
840-
this.import_dummy_binding(import);
841-
}
842-
Ok(binding) => {
843-
let imported_binding = this.import(binding, import);
844-
target_bindings[ns].set(Some(imported_binding));
845-
this.define(parent, target, ns, imported_binding);
846-
}
847850
}
848851
}
849852
});
@@ -876,10 +879,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
876879
self.r.unusable_binding = orig_unusable_binding;
877880
}
878881
import.vis.set(orig_vis);
879-
if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res {
880-
// Consider erroneous imports used to avoid duplicate diagnostics.
881-
self.r.used_imports.insert(import.id);
882-
}
883882
let module = match path_res {
884883
PathResult::Module(module) => {
885884
// Consistency checks, analogous to `finalize_macro_resolutions`.
@@ -1144,7 +1143,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
11441143
})
11451144
} else {
11461145
// `resolve_ident_in_module` reported a privacy error.
1147-
self.r.import_dummy_binding(import);
11481146
None
11491147
};
11501148
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Regression test for issue #95879.
2+
3+
use unresolved_crate::module::Name; //~ ERROR failed to resolve
4+
5+
/// [Name]
6+
pub struct S;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0433]: failed to resolve: maybe a missing crate `unresolved_crate`?
2+
--> $DIR/unresolved-import-recovery.rs:3:5
3+
|
4+
LL | use unresolved_crate::module::Name;
5+
| ^^^^^^^^^^^^^^^^ maybe a missing crate `unresolved_crate`?
6+
7+
error: Compilation failed, aborting rustdoc
8+
9+
error: aborting due to 2 previous errors
10+
11+
For more information about this error, try `rustc --explain E0433`.

src/test/ui/use/use-super-global-path.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mod foo {
99

1010
pub fn g() {
1111
use ::super::main; //~ ERROR global paths cannot start with `super`
12-
main(); //~ ERROR cannot find function `main` in this scope
12+
main();
1313
}
1414
}
1515

src/test/ui/use/use-super-global-path.stderr

+2-14
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,6 @@ error[E0433]: failed to resolve: global paths cannot start with `super`
1616
LL | use ::super::main;
1717
| ^^^^^ global paths cannot start with `super`
1818

19-
error[E0425]: cannot find function `main` in this scope
20-
--> $DIR/use-super-global-path.rs:12:9
21-
|
22-
LL | main();
23-
| ^^^^ not found in this scope
24-
|
25-
help: consider importing this function
26-
|
27-
LL | use main;
28-
|
29-
30-
error: aborting due to 4 previous errors
19+
error: aborting due to 3 previous errors
3120

32-
Some errors have detailed explanations: E0425, E0433.
33-
For more information about an error, try `rustc --explain E0425`.
21+
For more information about this error, try `rustc --explain E0433`.

0 commit comments

Comments
 (0)