about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbohan <bohan-zhang@foxmail.com>2023-03-19 20:12:57 +0800
committerbohan <bohan-zhang@foxmail.com>2023-03-19 20:18:45 +0800
commit177572241076e4885c5c12e407d3ea10d3b2363f (patch)
tree0fdba88d34411b8c4fbce558a94ade60daacf582
parentab9bb3ea368b2412531a3e8c07ba73d1dd690134 (diff)
downloadrust-177572241076e4885c5c12e407d3ea10d3b2363f.tar.gz
rust-177572241076e4885c5c12e407d3ea10d3b2363f.zip
fix: modify the condition that `resolve_imports` stops
-rw-r--r--compiler/rustc_resolve/src/imports.rs38
-rw-r--r--tests/ui/macros/nested-use-as.rs83
2 files changed, 106 insertions, 15 deletions
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 6e27bcc5bf3..4d4bc1be349 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -423,13 +423,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     /// Resolves all imports for the crate. This method performs the fixed-
     /// point iteration.
     pub(crate) fn resolve_imports(&mut self) {
-        let mut prev_num_indeterminates = self.indeterminate_imports.len() + 1;
-        while self.indeterminate_imports.len() < prev_num_indeterminates {
-            prev_num_indeterminates = self.indeterminate_imports.len();
+        let mut prev_indeterminate_count = usize::MAX;
+        let mut indeterminate_count = self.indeterminate_imports.len() * 3;
+        while indeterminate_count < prev_indeterminate_count {
+            prev_indeterminate_count = indeterminate_count;
+            indeterminate_count = 0;
             for import in mem::take(&mut self.indeterminate_imports) {
-                match self.resolve_import(&import) {
-                    true => self.determined_imports.push(import),
-                    false => self.indeterminate_imports.push(import),
+                let import_indeterminate_count = self.resolve_import(&import);
+                indeterminate_count += import_indeterminate_count;
+                match import_indeterminate_count {
+                    0 => self.determined_imports.push(import),
+                    _ => self.indeterminate_imports.push(import),
                 }
             }
         }
@@ -581,9 +585,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         diag.emit();
     }
 
-    /// Attempts to resolve the given import, returning true if its resolution is determined.
-    /// If successful, the resolved bindings are written into the module.
-    fn resolve_import(&mut self, import: &'a Import<'a>) -> bool {
+    /// Attempts to resolve the given import, returning:
+    /// - `0` means its resolution is determined.
+    /// - Other values mean that indeterminate exists under certain namespaces.
+    ///
+    /// Meanwhile, if resolve successful, the resolved bindings are written
+    /// into the module.
+    fn resolve_import(&mut self, import: &'a Import<'a>) -> usize {
         debug!(
             "(resolving import for module) resolving import `{}::...` in `{}`",
             Segment::names_to_string(&import.module_path),
@@ -601,8 +609,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
             match path_res {
                 PathResult::Module(module) => module,
-                PathResult::Indeterminate => return false,
-                PathResult::NonModule(..) | PathResult::Failed { .. } => return true,
+                PathResult::Indeterminate => return 3,
+                PathResult::NonModule(..) | PathResult::Failed { .. } => return 0,
             }
         };
 
@@ -618,12 +626,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             } => (source, target, source_bindings, target_bindings, type_ns_only),
             ImportKind::Glob { .. } => {
                 self.resolve_glob_import(import);
-                return true;
+                return 0;
             }
             _ => unreachable!(),
         };
 
-        let mut indeterminate = false;
+        let mut indeterminate_count = 0;
         self.per_ns(|this, ns| {
             if !type_ns_only || ns == TypeNS {
                 if let Err(Undetermined) = source_bindings[ns].get() {
@@ -646,7 +654,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
                 let parent = import.parent_scope.module;
                 match source_bindings[ns].get() {
-                    Err(Undetermined) => indeterminate = true,
+                    Err(Undetermined) => indeterminate_count += 1,
                     // Don't update the resolution, because it was never added.
                     Err(Determined) if target.name == kw::Underscore => {}
                     Ok(binding) if binding.is_importable() => {
@@ -670,7 +678,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
         });
 
-        !indeterminate
+        indeterminate_count
     }
 
     /// Performs final import resolution, consistency checks and error reporting.
diff --git a/tests/ui/macros/nested-use-as.rs b/tests/ui/macros/nested-use-as.rs
new file mode 100644
index 00000000000..21aa81e8092
--- /dev/null
+++ b/tests/ui/macros/nested-use-as.rs
@@ -0,0 +1,83 @@
+// check-pass
+// edition:2018
+// issue: https://github.com/rust-lang/rust/issues/97534
+
+macro_rules! m {
+    () => {
+        macro_rules! foo {
+            () => {}
+        }
+        use foo as bar;
+    }
+}
+
+m!{}
+
+use bar as baz;
+
+baz!{}
+
+macro_rules! foo2 {
+    () => {};
+}
+
+macro_rules! m2 {
+    () => {
+        use foo2 as bar2;
+    };
+}
+
+m2! {}
+
+use bar2 as baz2;
+
+baz2! {}
+
+macro_rules! n1 {
+    () => {
+        macro_rules! n2 {
+            () => {
+                macro_rules! n3 {
+                    () => {
+                        macro_rules! n4 {
+                            () => {}
+                        }
+                        use n4 as c4;
+                    }
+                }
+                use n3 as c3;
+            }
+        }
+        use n2 as c2;
+    }
+}
+
+use n1 as c1;
+c1!{}
+use c2 as a2;
+a2!{}
+use c3 as a3;
+a3!{}
+use c4 as a4;
+a4!{}
+
+// https://github.com/rust-lang/rust/pull/108729#issuecomment-1474750675
+// reversed
+use d5 as d6;
+use d4 as d5;
+use d3 as d4;
+use d2 as d3;
+use d1 as d2;
+use foo2 as d1;
+d6! {}
+
+// mess
+use f3 as f4;
+f5! {}
+use f1 as f2;
+use f4 as f5;
+use f2 as f3;
+use foo2 as f1;
+
+fn main() {
+}