Skip to content

Commit 89bf3ed

Browse files
Resolver: Batched import resolution.
Collect side effects from the current set of undetermined imports and only apply them at the end.
1 parent 91ee6a4 commit 89bf3ed

File tree

10 files changed

+244
-140
lines changed

10 files changed

+244
-140
lines changed

compiler/rustc_hir/src/def.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,24 @@ impl<T> PerNS<T> {
722722
pub fn iter(&self) -> IntoIter<&T, 3> {
723723
[&self.value_ns, &self.type_ns, &self.macro_ns].into_iter()
724724
}
725+
726+
pub fn into_iter_with(self) -> IntoIter<(Namespace, T), 3> {
727+
[
728+
(Namespace::TypeNS, self.type_ns),
729+
(Namespace::ValueNS, self.value_ns),
730+
(Namespace::MacroNS, self.macro_ns),
731+
]
732+
.into_iter()
733+
}
734+
735+
pub fn iter_with(&self) -> IntoIter<(Namespace, &T), 3> {
736+
[
737+
(Namespace::TypeNS, &self.type_ns),
738+
(Namespace::ValueNS, &self.value_ns),
739+
(Namespace::MacroNS, &self.macro_ns),
740+
]
741+
.into_iter()
742+
}
725743
}
726744

727745
impl<T> ::std::ops::Index<Namespace> for PerNS<T> {

compiler/rustc_resolve/src/imports.rs

Lines changed: 141 additions & 59 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,96 @@ use crate::{
4142

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

45+
struct ImportResolver<'r, 'ra, 'tcx> {
46+
r: CmResolver<'r, 'ra, 'tcx>, // always immutable
47+
outputs: ImportResolutionOutputs<'ra>,
48+
}
49+
50+
enum SideEffect<'ra> {
51+
None,
52+
Single { import_bindings: PerNS<PendingBinding<'ra>> },
53+
Glob { import_bindings: Vec<(NameBinding<'ra>, BindingKey, bool /* warn_ambiguity */)> },
54+
}
55+
56+
#[derive(Default)]
57+
struct ImportResolutionOutputs<'ra> {
58+
indeterminate_imports: Vec<Import<'ra>>,
59+
determined_imports: Vec<(Import<'ra>, SideEffect<'ra>)>,
60+
}
61+
62+
impl<'ra> ImportResolutionOutputs<'ra> {
63+
fn commit<'tcx>(self, r: &mut Resolver<'ra, 'tcx>) {
64+
r.indeterminate_imports = self.indeterminate_imports;
65+
r.determined_imports.reserve(self.determined_imports.len());
66+
67+
for (import, side_effect) in self.determined_imports {
68+
r.determined_imports.push(import);
69+
70+
let parent = import.parent_scope.module;
71+
match (&import.kind, side_effect) {
72+
(
73+
ImportKind::Single { target, bindings, .. },
74+
SideEffect::Single { import_bindings },
75+
) => {
76+
for (ns, pending_binding) in import_bindings.into_iter_with() {
77+
match pending_binding {
78+
PendingBinding::Ready(Some(binding)) => {
79+
r.define_binding_local(parent, *target, ns, binding);
80+
}
81+
PendingBinding::Ready(None) => {
82+
let key = BindingKey::new(*target, ns);
83+
r.update_local_resolution(parent, key, false, |_, resolution| {
84+
resolution.single_imports.swap_remove(&import);
85+
});
86+
}
87+
_ => {}
88+
}
89+
bindings[ns].set(pending_binding);
90+
}
91+
}
92+
(ImportKind::Glob { id, .. }, SideEffect::Glob { import_bindings }) => {
93+
let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap()
94+
else {
95+
unreachable!();
96+
};
97+
98+
module.glob_importers.borrow_mut().push(import);
99+
100+
for (binding, key, warn_ambiguity) in import_bindings {
101+
let _ = r.try_define_local(
102+
parent,
103+
key.ident.0,
104+
key.ns,
105+
binding,
106+
warn_ambiguity,
107+
);
108+
}
109+
110+
r.record_partial_res(*id, PartialRes::new(module.res().unwrap()));
111+
}
112+
113+
(_, SideEffect::None) => {}
114+
// Something weird happened, which shouldn't have happened.
115+
_ => unreachable!("Mismatched import kind and side effect"),
116+
}
117+
}
118+
}
119+
}
120+
121+
impl<'r, 'ra, 'tcx> Deref for ImportResolver<'r, 'ra, 'tcx> {
122+
type Target = Resolver<'ra, 'tcx>;
123+
124+
fn deref(&self) -> &Self::Target {
125+
self.r.deref()
126+
}
127+
}
128+
129+
impl<'r, 'ra, 'tcx> AsRef<Resolver<'ra, 'tcx>> for ImportResolver<'r, 'ra, 'tcx> {
130+
fn as_ref(&self) -> &Resolver<'ra, 'tcx> {
131+
self.r.as_ref()
132+
}
133+
}
134+
44135
/// A [`NameBinding`] in the process of being resolved.
45136
#[derive(Clone, Copy, Default, PartialEq)]
46137
pub(crate) enum PendingBinding<'ra> {
@@ -551,22 +642,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
551642
/// Resolves all imports for the crate. This method performs the fixed-
552643
/// point iteration.
553644
pub(crate) fn resolve_imports(&mut self) {
554-
self.assert_speculative = true;
555645
let mut prev_indeterminate_count = usize::MAX;
556646
let mut indeterminate_count = self.indeterminate_imports.len() * 3;
557647
while indeterminate_count < prev_indeterminate_count {
558648
prev_indeterminate_count = indeterminate_count;
559-
indeterminate_count = 0;
560-
for import in mem::take(&mut self.indeterminate_imports) {
561-
let import_indeterminate_count = self.cm().resolve_import(import);
562-
indeterminate_count += import_indeterminate_count;
563-
match import_indeterminate_count {
564-
0 => self.determined_imports.push(import),
565-
_ => self.indeterminate_imports.push(import),
566-
}
649+
let batch = mem::take(&mut self.indeterminate_imports);
650+
self.assert_speculative = true;
651+
let (outputs, count) =
652+
ImportResolver { r: self.cm(), outputs: Default::default() }.resolve_batch(batch);
653+
self.assert_speculative = false;
654+
indeterminate_count = count;
655+
outputs.commit(self);
656+
}
657+
}
658+
659+
fn resolve_batch<'r>(
660+
mut self: ImportResolver<'r, 'ra, 'tcx>,
661+
batch: Vec<Import<'ra>>,
662+
) -> (ImportResolutionOutputs<'ra>, usize) {
663+
let mut indeterminate_count = 0;
664+
for import in batch {
665+
let (side_effect, import_indeterminate_count) = self.resolve_import(import);
666+
indeterminate_count += import_indeterminate_count;
667+
match import_indeterminate_count {
668+
0 => self.outputs.determined_imports.push((import, side_effect)),
669+
_ => self.outputs.indeterminate_imports.push(import),
567670
}
568671
}
569-
self.assert_speculative = false;
672+
(self.outputs, indeterminate_count)
570673
}
571674

572675
pub(crate) fn finalize_imports(&mut self) {
@@ -839,7 +942,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
839942
///
840943
/// Meanwhile, if resolve successful, the resolved bindings are written
841944
/// into the module.
842-
fn resolve_import<'r>(mut self: CmResolver<'r, 'ra, 'tcx>, import: Import<'ra>) -> usize {
945+
fn resolve_import<'r>(
946+
self: &mut ImportResolver<'r, 'ra, 'tcx>,
947+
import: Import<'ra>,
948+
) -> (SideEffect<'ra>, usize) {
843949
debug!(
844950
"(resolving import for module) resolving import `{}::...` in `{}`",
845951
Segment::names_to_string(&import.module_path),
@@ -848,7 +954,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
848954
let module = if let Some(module) = import.imported_module.get() {
849955
module
850956
} else {
851-
let path_res = self.reborrow().maybe_resolve_path(
957+
let path_res = self.r.reborrow().maybe_resolve_path(
852958
&import.module_path,
853959
None,
854960
&import.parent_scope,
@@ -857,8 +963,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
857963

858964
match path_res {
859965
PathResult::Module(module) => module,
860-
PathResult::Indeterminate => return 3,
861-
PathResult::NonModule(..) | PathResult::Failed { .. } => return 0,
966+
PathResult::Indeterminate => return (SideEffect::None, 3),
967+
PathResult::NonModule(..) | PathResult::Failed { .. } => {
968+
return (SideEffect::None, 0);
969+
}
862970
}
863971
};
864972

@@ -868,16 +976,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
868976
(source, target, bindings, type_ns_only)
869977
}
870978
ImportKind::Glob { .. } => {
871-
// FIXME: Use mutable resolver directly as a hack, this should be an output of
872-
// speculative resolution.
873-
self.get_mut_unchecked().resolve_glob_import(import);
874-
return 0;
979+
return (self.resolve_glob_import(import), 0);
875980
}
876981
_ => unreachable!(),
877982
};
878983

984+
let mut import_bindings = PerNS::default();
879985
let mut indeterminate_count = 0;
880-
self.per_ns_cm(|this, ns| {
986+
self.r.reborrow().per_ns_cm(|this, ns| {
881987
if !type_ns_only || ns == TypeNS {
882988
if bindings[ns].get() != PendingBinding::Pending {
883989
return;
@@ -889,8 +995,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
889995
&import.parent_scope,
890996
Some(import),
891997
);
892-
let parent = import.parent_scope.module;
893-
let binding = match binding_result {
998+
let pending_binding = match binding_result {
894999
Ok(binding) => {
8951000
if binding.is_assoc_item()
8961001
&& !this.tcx.features().import_trait_associated_functions()
@@ -905,43 +1010,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
9051010
}
9061011
// We need the `target`, `source` can be extracted.
9071012
let imported_binding = this.import(binding, import);
908-
// FIXME: Use mutable resolver directly as a hack, this should be an output of
909-
// speculative resolution.
910-
this.get_mut_unchecked().define_binding_local(
911-
parent,
912-
target,
913-
ns,
914-
imported_binding,
915-
);
9161013
PendingBinding::Ready(Some(imported_binding))
9171014
}
9181015
Err(Determinacy::Determined) => {
9191016
// Don't remove underscores from `single_imports`, they were never added.
920-
if target.name != kw::Underscore {
921-
let key = BindingKey::new(target, ns);
922-
// FIXME: Use mutable resolver directly as a hack, this should be an output of
923-
// speculative resolution.
924-
this.get_mut_unchecked().update_local_resolution(
925-
parent,
926-
key,
927-
false,
928-
|_, resolution| {
929-
resolution.single_imports.swap_remove(&import);
930-
},
931-
);
1017+
if target.name == kw::Underscore {
1018+
return;
9321019
}
9331020
PendingBinding::Ready(None)
9341021
}
9351022
Err(Determinacy::Undetermined) => {
9361023
indeterminate_count += 1;
937-
PendingBinding::Pending
1024+
return;
9381025
}
9391026
};
940-
bindings[ns].set(binding);
1027+
import_bindings[ns] = pending_binding;
9411028
}
9421029
});
9431030

944-
indeterminate_count
1031+
(SideEffect::Single { import_bindings }, indeterminate_count)
9451032
}
9461033

9471034
/// Performs final import resolution, consistency checks and error reporting.
@@ -1484,13 +1571,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
14841571
false
14851572
}
14861573

1487-
fn resolve_glob_import(&mut self, import: Import<'ra>) {
1574+
fn resolve_glob_import<'r>(
1575+
self: &mut ImportResolver<'r, 'ra, 'tcx>,
1576+
import: Import<'ra>,
1577+
) -> SideEffect<'ra> {
14881578
// This function is only called for glob imports.
1489-
let ImportKind::Glob { id, .. } = import.kind else { unreachable!() };
1579+
let ImportKind::Glob { .. } = import.kind else { unreachable!() };
14901580

14911581
let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else {
14921582
self.dcx().emit_err(CannotGlobImportAllCrates { span: import.span });
1493-
return;
1583+
return SideEffect::None;
14941584
};
14951585

14961586
if module.is_trait() && !self.tcx.features().import_trait_associated_functions() {
@@ -1504,12 +1594,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15041594
}
15051595

15061596
if module == import.parent_scope.module {
1507-
return;
1597+
return SideEffect::None;
15081598
}
15091599

1510-
// Add to module's glob_importers
1511-
module.glob_importers.borrow_mut().push(import);
1512-
15131600
// Ensure that `resolutions` isn't borrowed during `try_define`,
15141601
// since it might get updated via a glob cycle.
15151602
let bindings = self
@@ -1520,6 +1607,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15201607
resolution.borrow().binding().map(|binding| (*key, binding))
15211608
})
15221609
.collect::<Vec<_>>();
1610+
let mut import_bindings = Vec::with_capacity(bindings.len());
15231611
for (mut key, binding) in bindings {
15241612
let scope = match key.ident.0.span.reverse_glob_adjust(module.expansion, import.span) {
15251613
Some(Some(def)) => self.expn_def_scope(def),
@@ -1532,18 +1620,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15321620
.resolution(import.parent_scope.module, key)
15331621
.and_then(|r| r.binding())
15341622
.is_some_and(|binding| binding.warn_ambiguity_recursive());
1535-
let _ = self.try_define_local(
1536-
import.parent_scope.module,
1537-
key.ident.0,
1538-
key.ns,
1539-
imported_binding,
1540-
warn_ambiguity,
1541-
);
1623+
import_bindings.push((imported_binding, key, warn_ambiguity));
15421624
}
15431625
}
15441626

15451627
// Record the destination of this import
1546-
self.record_partial_res(id, PartialRes::new(module.res().unwrap()));
1628+
SideEffect::Glob { import_bindings }
15471629
}
15481630

15491631
// Miscellaneous post-processing, including recording re-exports,

compiler/rustc_resolve/src/lib.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2541,12 +2541,6 @@ mod ref_mut {
25412541
true => self.p,
25422542
}
25432543
}
2544-
2545-
/// Returns a mutable reference to the inner value without checking if
2546-
/// it's in a mutable state.
2547-
pub(crate) fn get_mut_unchecked(&mut self) -> &mut T {
2548-
self.p
2549-
}
25502544
}
25512545
}
25522546

fail.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#![no_core]
2+
#![feature(no_core)]
3+
#![allow(internal_features)]
4+
#![feature(lang_items)]
5+
6+
#[lang = "sized"]
7+
pub trait Sized: MetaSized {}
8+
9+
#[lang = "meta_sized"]
10+
pub trait MetaSized: PointeeSized {}
11+
12+
#[lang = "pointee_sized"]
13+
pub trait PointeeSized {}
14+
15+
mod core_simd {
16+
mod vector {
17+
pub struct Simd {}
18+
}
19+
pub mod simd {
20+
pub use crate::core_simd::vector::*;
21+
}
22+
}
23+
24+
pub mod simd {
25+
pub use crate::core_simd::simd::*;
26+
}
27+
28+
mod fail {
29+
use crate::simd::Simd;
30+
}

0 commit comments

Comments
 (0)