about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-05-19 00:41:32 +0000
committerbors <bors@rust-lang.org>2023-05-19 00:41:32 +0000
commit92f5dea0ebe2e34ad8411e8cd8a0c97dd45b3400 (patch)
tree599b16ef1b643e5f18ea1b8d4baacd3fc1b5067c
parentc9dc55d05c9a111300271b7f8b8f62220ce9ad1e (diff)
parentf34678c0976086523f56a0f974e76cfc5ca2fc40 (diff)
downloadrust-92f5dea0ebe2e34ad8411e8cd8a0c97dd45b3400.tar.gz
rust-92f5dea0ebe2e34ad8411e8cd8a0c97dd45b3400.zip
Auto merge of #109602 - bvanjoi:fix-issue-109343, r=petrochenkov
fix(resolve): replace bindings to dummy for unresolved imports

close #109343

In #109343, `f` in `pub use f as g` points to:

|namespace| binding|
|-|-|
|type| `external crate f`|
|value| `None` |
|macro| `None` |

When resolve `value_ns` during `resolve_doc_links`, the value of the binding of single_import `pub use f as g` goes to `pub use inner::f`, and since it does not satisfy [!self.is_accessible_from(binding.vis, single_import.parent_scope.module)](https://github.com/rust-lang/rust/blob/master/compiler/rustc_resolve/src/ident.rs#L971) and returns `Err(Undetermined)`, which eventually goes to `PathResult::Indeterminate => unreachable!`.

This PR replace all namespace binding to `dummy_binding` for indeterminate import, so, the bindings of `pub use f as g` had been changed to followings after finalize:

|namespace| binding|
|-|-|
|type| `dummy`|
|value| `dummy` |
|macro| `dummy` |

r?`@petrochenkov`
-rw-r--r--compiler/rustc_resolve/src/imports.rs11
-rw-r--r--compiler/rustc_resolve/src/lib.rs1
-rw-r--r--compiler/rustc_session/src/config.rs2
-rw-r--r--tests/ui/imports/issue-109343.rs10
-rw-r--r--tests/ui/imports/issue-109343.stderr11
5 files changed, 29 insertions, 6 deletions
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 0e90703faec..7c4c05d4b94 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -405,11 +405,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         t
     }
 
-    // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed resolution,
-    // also mark such failed imports as used to avoid duplicate diagnostics.
-    fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
+    // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed
+    // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics.
+    fn import_dummy_binding(&mut self, import: &'a Import<'a>, is_indeterminate: bool) {
         if let ImportKind::Single { target, ref target_bindings, .. } = import.kind {
-            if target_bindings.iter().any(|binding| binding.get().is_some()) {
+            if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none()))
+            {
                 return; // Has resolution, do not create the dummy binding
             }
             let dummy_binding = self.dummy_binding;
@@ -474,7 +475,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
             // If this import is unresolved then create a dummy import
             // resolution for it so that later resolve stages won't complain.
-            self.import_dummy_binding(import);
+            self.import_dummy_binding(import, is_indeterminate);
 
             if let Some(err) = unresolved_import_error {
                 if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 14a3671c01d..3cdc3f0ecf8 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -85,6 +85,7 @@ pub mod rustdoc;
 
 fluent_messages! { "../messages.ftl" }
 
+#[derive(Debug)]
 enum Weak {
     Yes,
     No,
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 39e255104d5..a328447aca9 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -421,7 +421,7 @@ pub enum TrimmedDefPaths {
     GoodPath,
 }
 
-#[derive(Clone, Hash)]
+#[derive(Clone, Hash, Debug)]
 pub enum ResolveDocLinks {
     /// Do not resolve doc links.
     None,
diff --git a/tests/ui/imports/issue-109343.rs b/tests/ui/imports/issue-109343.rs
new file mode 100644
index 00000000000..0c10259bcd7
--- /dev/null
+++ b/tests/ui/imports/issue-109343.rs
@@ -0,0 +1,10 @@
+#![crate_type = "lib"]
+
+pub mod f {}
+pub use unresolved::f;
+//~^ ERROR unresolved import `unresolved`
+
+/// [g]
+pub use f as g;
+
+fn main() {}
diff --git a/tests/ui/imports/issue-109343.stderr b/tests/ui/imports/issue-109343.stderr
new file mode 100644
index 00000000000..8d9a3aee980
--- /dev/null
+++ b/tests/ui/imports/issue-109343.stderr
@@ -0,0 +1,11 @@
+error[E0432]: unresolved import `unresolved`
+  --> $DIR/issue-109343.rs:4:9
+   |
+LL | pub use unresolved::f;
+   |         ^^^^^^^^^^ maybe a missing crate `unresolved`?
+   |
+   = help: consider adding `extern crate unresolved` to use the `unresolved` crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.