Skip to content

Commit 77f5e5c

Browse files
design of ImportResolver, which does the batched resolution
1 parent 2886b36 commit 77f5e5c

File tree

2 files changed

+73
-15
lines changed

2 files changed

+73
-15
lines changed

compiler/rustc_resolve/src/imports.rs

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use std::cell::Cell;
44
use std::mem;
5+
use std::ops::Deref;
56

67
use rustc_ast::NodeId;
78
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
@@ -41,6 +42,53 @@ use crate::{
4142

4243
type Res = def::Res<NodeId>;
4344

45+
pub(crate) struct ImportResolver<'r, 'ra, 'tcx> {
46+
r: CmResolver<'r, 'ra, 'tcx>, // always immutable
47+
batch: Vec<Import<'ra>>, // a.k.a. indeterminate_imports, also treated as output
48+
49+
// outputs
50+
determined_imports: Vec<Import<'ra>>,
51+
}
52+
53+
struct ImportResolutionOutputs<'ra> {
54+
indeterminate_imports: Vec<Import<'ra>>,
55+
determined_imports: Vec<Import<'ra>>,
56+
}
57+
58+
impl<'r, 'ra, 'tcx> ImportResolver<'r, 'ra, 'tcx> {
59+
pub(crate) fn new(cmr: CmResolver<'r, 'ra, 'tcx>, batch: Vec<Import<'ra>>) -> Self {
60+
ImportResolver { r: cmr, batch, determined_imports: Vec::new() }
61+
}
62+
63+
fn into_outputs(self) -> ImportResolutionOutputs<'ra> {
64+
ImportResolutionOutputs {
65+
indeterminate_imports: self.batch,
66+
determined_imports: self.determined_imports,
67+
}
68+
}
69+
}
70+
71+
impl<'ra> ImportResolutionOutputs<'ra> {
72+
fn commit<'tcx>(self, r: &mut Resolver<'ra, 'tcx>) {
73+
r.indeterminate_imports = self.indeterminate_imports;
74+
r.determined_imports.extend(self.determined_imports);
75+
}
76+
}
77+
78+
impl<'r, 'ra, 'tcx> Deref for ImportResolver<'r, 'ra, 'tcx> {
79+
type Target = Resolver<'ra, 'tcx>;
80+
81+
fn deref(&self) -> &Self::Target {
82+
self.r.deref()
83+
}
84+
}
85+
86+
impl<'r, 'ra, 'tcx> AsRef<Resolver<'ra, 'tcx>> for ImportResolver<'r, 'ra, 'tcx> {
87+
fn as_ref(&self) -> &Resolver<'ra, 'tcx> {
88+
self.r.as_ref()
89+
}
90+
}
91+
4492
/// A [`NameBinding`] in the process of being resolved.
4593
#[derive(Clone, Copy, Default, PartialEq)]
4694
pub(crate) enum PendingBinding<'ra> {
@@ -552,22 +600,32 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
552600
/// Resolves all imports for the crate. This method performs the fixed-
553601
/// point iteration.
554602
pub(crate) fn resolve_imports(&mut self) {
555-
self.assert_speculative = true;
556603
let mut prev_indeterminate_count = usize::MAX;
557604
let mut indeterminate_count = self.indeterminate_imports.len() * 3;
558605
while indeterminate_count < prev_indeterminate_count {
606+
self.assert_speculative = true;
559607
prev_indeterminate_count = indeterminate_count;
560-
indeterminate_count = 0;
561-
for import in mem::take(&mut self.indeterminate_imports) {
562-
let import_indeterminate_count = self.cm().resolve_import(import);
563-
indeterminate_count += import_indeterminate_count;
564-
match import_indeterminate_count {
565-
0 => self.determined_imports.push(import),
566-
_ => self.indeterminate_imports.push(import),
567-
}
608+
let batch = mem::take(&mut self.indeterminate_imports);
609+
let (outputs, count) = ImportResolver::new(self.cm(), batch).resolve_batch();
610+
indeterminate_count = count;
611+
self.assert_speculative = false;
612+
outputs.commit(self);
613+
}
614+
}
615+
616+
fn resolve_batch<'r>(
617+
mut self: ImportResolver<'r, 'ra, 'tcx>,
618+
) -> (ImportResolutionOutputs<'ra>, usize) {
619+
let mut indeterminate_count = 0;
620+
for import in mem::take(&mut self.batch) {
621+
let import_indeterminate_count = self.resolve_import(import);
622+
indeterminate_count += import_indeterminate_count;
623+
match import_indeterminate_count {
624+
0 => self.determined_imports.push(import),
625+
_ => self.batch.push(import),
568626
}
569627
}
570-
self.assert_speculative = false;
628+
(self.into_outputs(), indeterminate_count)
571629
}
572630

573631
pub(crate) fn finalize_imports(&mut self) {
@@ -840,7 +898,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
840898
///
841899
/// Meanwhile, if resolve successful, the resolved bindings are written
842900
/// into the module.
843-
fn resolve_import<'r>(mut self: CmResolver<'r, 'ra, 'tcx>, import: Import<'ra>) -> usize {
901+
fn resolve_import<'r>(self: &mut ImportResolver<'r, 'ra, 'tcx>, import: Import<'ra>) -> usize {
844902
debug!(
845903
"(resolving import for module) resolving import `{}::...` in `{}`",
846904
Segment::names_to_string(&import.module_path),
@@ -849,7 +907,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
849907
let module = if let Some(module) = import.imported_module.get() {
850908
module
851909
} else {
852-
let path_res = self.reborrow().maybe_resolve_path(
910+
let path_res = self.r.reborrow().maybe_resolve_path(
853911
&import.module_path,
854912
None,
855913
&import.parent_scope,
@@ -871,14 +929,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
871929
ImportKind::Glob { .. } => {
872930
// FIXME: Use mutable resolver directly as a hack, this should be an output of
873931
// specualtive resolution.
874-
self.get_mut_unchecked().resolve_glob_import(import);
932+
self.r.get_mut_unchecked().resolve_glob_import(import);
875933
return 0;
876934
}
877935
_ => unreachable!(),
878936
};
879937

880938
let mut indeterminate_count = 0;
881-
self.per_ns_cm(|this, ns| {
939+
self.r.reborrow().per_ns_cm(|this, ns| {
882940
if !type_ns_only || ns == TypeNS {
883941
if bindings[ns].get() != PendingBinding::Pending {
884942
return;

compiler/rustc_resolve/src/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
238238
}
239239

240240
fn resolve_imports(&mut self) {
241-
self.resolve_imports()
241+
self.resolve_imports();
242242
}
243243

244244
fn resolve_macro_invocation(

0 commit comments

Comments
 (0)