Skip to content

Commit 0a8acac

Browse files
authored
Rollup merge of #95887 - petrochenkov:doclink5, r=cjgillot
resolve: Create dummy bindings for all unresolved imports Apparently such bindings weren't previously created for all unresolved imports, causing issues like #95879. In this PR I'm trying to create such dummy bindings in a more centralized way by calling `import_dummy_binding` once for all imports in `finalize_imports`. Fixes #95879.
2 parents c842240 + 09195d3 commit 0a8acac

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
@@ -310,18 +310,23 @@ impl<'a> Resolver<'a> {
310310
t
311311
}
312312

313-
// Define a "dummy" resolution containing a Res::Err as a placeholder for a
314-
// failed resolution
313+
// Define a dummy resolution containing a `Res::Err` as a placeholder for a failed resolution,
314+
// also mark such failed imports as used to avoid duplicate diagnostics.
315315
fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
316-
if let ImportKind::Single { target, .. } = import.kind {
316+
if let ImportKind::Single { target, ref target_bindings, .. } = import.kind {
317+
if target_bindings.iter().any(|binding| binding.get().is_some()) {
318+
return; // Has resolution, do not create the dummy binding
319+
}
317320
let dummy_binding = self.dummy_binding;
318321
let dummy_binding = self.import(dummy_binding, import);
319322
self.per_ns(|this, ns| {
320323
let key = this.new_key(target, ns);
321324
let _ = this.try_define(import.parent_scope.module, key, dummy_binding);
322325
});
323-
// Consider erroneous imports used to avoid duplicate diagnostics.
324326
self.record_use(target, dummy_binding, false);
327+
} else if import.imported_module.get().is_none() {
328+
import.used.set(true);
329+
self.used_imports.insert(import.id);
325330
}
326331
}
327332
}
@@ -386,7 +391,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
386391
.map(|i| (false, i))
387392
.chain(indeterminate_imports.into_iter().map(|i| (true, i)))
388393
{
389-
if let Some(err) = self.finalize_import(import) {
394+
let unresolved_import_error = self.finalize_import(import);
395+
396+
// If this import is unresolved then create a dummy import
397+
// resolution for it so that later resolve stages won't complain.
398+
self.r.import_dummy_binding(import);
399+
400+
if let Some(err) = unresolved_import_error {
390401
if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
391402
if source.name == kw::SelfLower {
392403
// Silence `unresolved import` error if E0429 is already emitted
@@ -396,9 +407,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
396407
}
397408
}
398409

399-
// If the error is a single failed import then create a "fake" import
400-
// resolution for it so that later resolve stages won't complain.
401-
self.r.import_dummy_binding(import);
402410
if prev_root_id.as_u32() != 0
403411
&& prev_root_id.as_u32() != import.root_id.as_u32()
404412
&& !errors.is_empty()
@@ -418,8 +426,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
418426
prev_root_id = import.root_id;
419427
}
420428
} else if is_indeterminate {
421-
// Consider erroneous imports used to avoid duplicate diagnostics.
422-
self.r.used_imports.insert(import.id);
423429
let path = import_path_to_string(
424430
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
425431
&import.kind,
@@ -553,26 +559,23 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
553559
Err(Undetermined) => indeterminate = true,
554560
// Don't update the resolution, because it was never added.
555561
Err(Determined) if target.name == kw::Underscore => {}
556-
Err(Determined) => {
562+
Ok(binding) if binding.is_importable() => {
563+
let imported_binding = this.import(binding, import);
564+
target_bindings[ns].set(Some(imported_binding));
565+
this.define(parent, target, ns, imported_binding);
566+
}
567+
source_binding @ (Ok(..) | Err(Determined)) => {
568+
if source_binding.is_ok() {
569+
let msg = format!("`{}` is not directly importable", target);
570+
struct_span_err!(this.session, import.span, E0253, "{}", &msg)
571+
.span_label(import.span, "cannot be imported directly")
572+
.emit();
573+
}
557574
let key = this.new_key(target, ns);
558575
this.update_resolution(parent, key, |_, resolution| {
559576
resolution.single_imports.remove(&Interned::new_unchecked(import));
560577
});
561578
}
562-
Ok(binding) if !binding.is_importable() => {
563-
let msg = format!("`{}` is not directly importable", target);
564-
struct_span_err!(this.session, import.span, E0253, "{}", &msg)
565-
.span_label(import.span, "cannot be imported directly")
566-
.emit();
567-
// Do not import this illegal binding. Import a dummy binding and pretend
568-
// everything is fine
569-
this.import_dummy_binding(import);
570-
}
571-
Ok(binding) => {
572-
let imported_binding = this.import(binding, import);
573-
target_bindings[ns].set(Some(imported_binding));
574-
this.define(parent, target, ns, imported_binding);
575-
}
576579
}
577580
}
578581
});
@@ -605,10 +608,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
605608
);
606609
let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len;
607610
import.vis.set(orig_vis);
608-
if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res {
609-
// Consider erroneous imports used to avoid duplicate diagnostics.
610-
self.r.used_imports.insert(import.id);
611-
}
612611
let module = match path_res {
613612
PathResult::Module(module) => {
614613
// Consistency checks, analogous to `finalize_macro_resolutions`.
@@ -872,7 +871,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
872871
})
873872
} else {
874873
// `resolve_ident_in_module` reported a privacy error.
875-
self.r.import_dummy_binding(import);
876874
None
877875
};
878876
}
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)