From 177572241076e4885c5c12e407d3ea10d3b2363f Mon Sep 17 00:00:00 2001 From: bohan Date: Sun, 19 Mar 2023 20:12:57 +0800 Subject: [PATCH] fix: modify the condition that `resolve_imports` stops --- compiler/rustc_resolve/src/imports.rs | 38 +++++++----- tests/ui/macros/nested-use-as.rs | 83 +++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 15 deletions(-) create mode 100644 tests/ui/macros/nested-use-as.rs 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() { +}