fix: modify the condition that resolve_imports stops

This commit is contained in:
bohan 2023-03-19 20:12:57 +08:00
parent ab9bb3ea36
commit 1775722410
2 changed files with 106 additions and 15 deletions

View File

@ -423,13 +423,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// Resolves all imports for the crate. This method performs the fixed- /// Resolves all imports for the crate. This method performs the fixed-
/// point iteration. /// point iteration.
pub(crate) fn resolve_imports(&mut self) { pub(crate) fn resolve_imports(&mut self) {
let mut prev_num_indeterminates = self.indeterminate_imports.len() + 1; let mut prev_indeterminate_count = usize::MAX;
while self.indeterminate_imports.len() < prev_num_indeterminates { let mut indeterminate_count = self.indeterminate_imports.len() * 3;
prev_num_indeterminates = self.indeterminate_imports.len(); while indeterminate_count < prev_indeterminate_count {
prev_indeterminate_count = indeterminate_count;
indeterminate_count = 0;
for import in mem::take(&mut self.indeterminate_imports) { for import in mem::take(&mut self.indeterminate_imports) {
match self.resolve_import(&import) { let import_indeterminate_count = self.resolve_import(&import);
true => self.determined_imports.push(import), indeterminate_count += import_indeterminate_count;
false => self.indeterminate_imports.push(import), 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(); diag.emit();
} }
/// Attempts to resolve the given import, returning true if its resolution is determined. /// Attempts to resolve the given import, returning:
/// If successful, the resolved bindings are written into the module. /// - `0` means its resolution is determined.
fn resolve_import(&mut self, import: &'a Import<'a>) -> bool { /// - 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!( debug!(
"(resolving import for module) resolving import `{}::...` in `{}`", "(resolving import for module) resolving import `{}::...` in `{}`",
Segment::names_to_string(&import.module_path), Segment::names_to_string(&import.module_path),
@ -601,8 +609,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
match path_res { match path_res {
PathResult::Module(module) => module, PathResult::Module(module) => module,
PathResult::Indeterminate => return false, PathResult::Indeterminate => return 3,
PathResult::NonModule(..) | PathResult::Failed { .. } => return true, 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), } => (source, target, source_bindings, target_bindings, type_ns_only),
ImportKind::Glob { .. } => { ImportKind::Glob { .. } => {
self.resolve_glob_import(import); self.resolve_glob_import(import);
return true; return 0;
} }
_ => unreachable!(), _ => unreachable!(),
}; };
let mut indeterminate = false; let mut indeterminate_count = 0;
self.per_ns(|this, ns| { self.per_ns(|this, ns| {
if !type_ns_only || ns == TypeNS { if !type_ns_only || ns == TypeNS {
if let Err(Undetermined) = source_bindings[ns].get() { if let Err(Undetermined) = source_bindings[ns].get() {
@ -646,7 +654,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let parent = import.parent_scope.module; let parent = import.parent_scope.module;
match source_bindings[ns].get() { match source_bindings[ns].get() {
Err(Undetermined) => indeterminate = true, Err(Undetermined) => indeterminate_count += 1,
// Don't update the resolution, because it was never added. // Don't update the resolution, because it was never added.
Err(Determined) if target.name == kw::Underscore => {} Err(Determined) if target.name == kw::Underscore => {}
Ok(binding) if binding.is_importable() => { 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. /// Performs final import resolution, consistency checks and error reporting.

View File

@ -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() {
}