Skip to content

Commit 1c3103a

Browse files
address review
1 parent 9bb25a6 commit 1c3103a

File tree

1 file changed

+143
-143
lines changed

1 file changed

+143
-143
lines changed

compiler/rustc_resolve/src/imports.rs

Lines changed: 143 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -41,125 +41,30 @@ use crate::{
4141

4242
type Res = def::Res<NodeId>;
4343

44+
/// The the side effect made when resolving the bindings for an underterminate import.
4445
enum SideEffectBindings<'ra> {
4546
None,
46-
Single { import_bindings: PerNS<PendingBinding<'ra>> },
47-
Glob { import_bindings: Vec<(NameBinding<'ra>, BindingKey, bool /* warn_ambiguity */)> },
47+
/// Side effect that should be applied to the field `bindings` of `ImportKind::Single`.
48+
///
49+
/// The inner `Option` is the actual side effect, it tells us wether we found a binding
50+
/// when resolving the import in this particular namespace.
51+
/// The outer `Option` tells us if this side effect is present.
52+
Single {
53+
import_bindings: PerNS<Option<Option<NameBinding<'ra>>>>,
54+
},
55+
Glob {
56+
import_bindings: Vec<(NameBinding<'ra>, BindingKey, bool /* warn_ambiguity */)>,
57+
},
4858
}
4959

60+
/// The side effect made when resolving an undeterminate import.
5061
struct SideEffect<'ra> {
5162
imported_module: ModuleOrUniformRoot<'ra>,
5263
bindings: SideEffectBindings<'ra>,
5364
}
5465

55-
#[derive(Default)]
56-
struct ImportResolutionOutputs<'ra> {
57-
indeterminate_imports: Vec<Import<'ra>>,
58-
determined_imports: Vec<(Import<'ra>, Option<SideEffect<'ra>>)>,
59-
}
60-
61-
impl<'ra> ImportResolutionOutputs<'ra> {
62-
fn new() -> Self {
63-
Default::default()
64-
}
65-
66-
fn commit<'tcx>(self, r: &mut Resolver<'ra, 'tcx>) {
67-
r.indeterminate_imports = self.indeterminate_imports;
68-
r.determined_imports.reserve(self.determined_imports.len());
69-
70-
for (import, side_effect) in self.determined_imports {
71-
r.determined_imports.push(import);
72-
73-
let Some(SideEffect { imported_module, bindings: side_effect_bindings }) = side_effect
74-
else {
75-
return;
76-
};
77-
import.imported_module.set(Some(imported_module));
78-
let parent = import.parent_scope.module;
79-
80-
match (&import.kind, side_effect_bindings) {
81-
(
82-
ImportKind::Single { target, bindings, .. },
83-
SideEffectBindings::Single { import_bindings },
84-
) => {
85-
r.per_ns(|this, ns| {
86-
match import_bindings[ns] {
87-
PendingBinding::Ready(Some(binding)) => {
88-
if binding.is_assoc_item()
89-
&& !this.tcx.features().import_trait_associated_functions()
90-
{
91-
feature_err(
92-
this.tcx.sess,
93-
sym::import_trait_associated_functions,
94-
import.span,
95-
"`use` associated items of traits is unstable",
96-
)
97-
.emit();
98-
}
99-
this.define_binding_local(parent, *target, ns, binding);
100-
}
101-
PendingBinding::Ready(None) => {
102-
// Don't remove underscores from `single_imports`, they were never added.
103-
if target.name != kw::Underscore {
104-
let key = BindingKey::new(*target, ns);
105-
this.update_local_resolution(
106-
parent,
107-
key,
108-
false,
109-
|_, resolution| {
110-
resolution.single_imports.swap_remove(&import);
111-
},
112-
);
113-
}
114-
}
115-
_ => {}
116-
}
117-
bindings[ns].set(import_bindings[ns]);
118-
});
119-
}
120-
(ImportKind::Glob { id, .. }, SideEffectBindings::Glob { import_bindings }) => {
121-
let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap()
122-
else {
123-
r.dcx().emit_err(CannotGlobImportAllCrates { span: import.span });
124-
continue;
125-
};
126-
127-
if module.is_trait() && !r.tcx.features().import_trait_associated_functions() {
128-
feature_err(
129-
r.tcx.sess,
130-
sym::import_trait_associated_functions,
131-
import.span,
132-
"`use` associated items of traits is unstable",
133-
)
134-
.emit();
135-
}
136-
137-
module.glob_importers.borrow_mut().push(import);
138-
139-
for (binding, key, warn_ambiguity) in import_bindings {
140-
let _ = r.try_define_local(
141-
parent,
142-
key.ident.0,
143-
key.ns,
144-
binding,
145-
warn_ambiguity,
146-
);
147-
}
148-
149-
r.record_partial_res(*id, PartialRes::new(module.res().unwrap()));
150-
}
151-
152-
(_, SideEffectBindings::None) => {}
153-
154-
// Something weird happened, which shouldn't have happened.
155-
_ => unreachable!("Mismatched import kind and side effect"),
156-
}
157-
}
158-
}
159-
}
160-
16166
/// A [`NameBinding`] in the process of being resolved.
162-
#[derive(Clone, Copy, Default, PartialEq)]
67+
#[derive(Clone, Copy, Default, PartialEq, Debug)]
16368
pub(crate) enum PendingBinding<'ra> {
16469
Ready(Option<NameBinding<'ra>>),
16570
#[default]
@@ -659,11 +564,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
659564

660565
// Import resolution
661566
//
662-
// This is a fixed-point algorithm. We resolve imports until our efforts
663-
// are stymied by an unresolved import; then we bail out of the current
664-
// module and continue. We terminate successfully once no more imports
665-
// remain or unsuccessfully when no forward progress in resolving imports
666-
// is made.
567+
// This is a batched fixed-point algorithm. Each import is resolved in
568+
// isolation, with any side effects collected for later.
569+
// After a full pass over the current set of `indeterminate_imports`,
570+
// the collected side effects are committed together. The process
571+
// repeats until either no imports remain or no further progress can
572+
// be made.
667573

668574
/// Resolves all imports for the crate. This method performs the fixed-
669575
/// point iteration.
@@ -672,18 +578,116 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
672578
let mut indeterminate_count = self.indeterminate_imports.len() * 3;
673579
while indeterminate_count < prev_indeterminate_count {
674580
prev_indeterminate_count = indeterminate_count;
675-
let mut outputs = ImportResolutionOutputs::new();
581+
indeterminate_count = 0;
582+
let mut import_resolutions = Vec::new();
676583
self.assert_speculative = true;
677584
for import in mem::take(&mut self.indeterminate_imports) {
678585
let (side_effect, import_indeterminate_count) = self.cm().resolve_import(import);
679586
indeterminate_count += import_indeterminate_count;
680587
match import_indeterminate_count {
681-
0 => outputs.determined_imports.push((import, side_effect)),
682-
_ => outputs.indeterminate_imports.push(import),
588+
0 => import_resolutions.push((import, side_effect)),
589+
_ => self.indeterminate_imports.push(import),
683590
}
684591
}
685592
self.assert_speculative = false;
686-
outputs.commit(self);
593+
self.commit_import_resolutions(import_resolutions);
594+
}
595+
}
596+
597+
fn commit_import_resolutions(
598+
&mut self,
599+
import_resolutions: Vec<(Import<'ra>, Option<SideEffect<'ra>>)>,
600+
) {
601+
self.determined_imports.reserve(self.determined_imports.len());
602+
603+
for (import, side_effect) in import_resolutions {
604+
self.determined_imports.push(import);
605+
606+
let Some(SideEffect { imported_module, bindings: side_effect_bindings }) = side_effect
607+
else {
608+
return;
609+
};
610+
import.imported_module.set(Some(imported_module));
611+
let parent = import.parent_scope.module;
612+
613+
match (&import.kind, side_effect_bindings) {
614+
(
615+
ImportKind::Single { target, bindings, .. },
616+
SideEffectBindings::Single { import_bindings },
617+
) => {
618+
self.per_ns(|this, ns| {
619+
match import_bindings[ns] {
620+
Some(Some(binding)) => {
621+
if binding.is_assoc_item()
622+
&& !this.tcx.features().import_trait_associated_functions()
623+
{
624+
feature_err(
625+
this.tcx.sess,
626+
sym::import_trait_associated_functions,
627+
import.span,
628+
"`use` associated items of traits is unstable",
629+
)
630+
.emit();
631+
}
632+
this.define_binding_local(parent, *target, ns, binding);
633+
bindings[ns].set(PendingBinding::Ready(Some(binding)));
634+
}
635+
Some(None) => {
636+
// Don't remove underscores from `single_imports`, they were never added.
637+
if target.name != kw::Underscore {
638+
let key = BindingKey::new(*target, ns);
639+
this.update_local_resolution(
640+
parent,
641+
key,
642+
false,
643+
|_, resolution| {
644+
resolution.single_imports.swap_remove(&import);
645+
},
646+
);
647+
}
648+
bindings[ns].set(PendingBinding::Ready(None));
649+
}
650+
None => return,
651+
}
652+
});
653+
}
654+
(ImportKind::Glob { id, .. }, SideEffectBindings::Glob { import_bindings }) => {
655+
let ModuleOrUniformRoot::Module(module) = imported_module else {
656+
self.dcx().emit_err(CannotGlobImportAllCrates { span: import.span });
657+
continue;
658+
};
659+
660+
if module.is_trait() && !self.tcx.features().import_trait_associated_functions()
661+
{
662+
feature_err(
663+
self.tcx.sess,
664+
sym::import_trait_associated_functions,
665+
import.span,
666+
"`use` associated items of traits is unstable",
667+
)
668+
.emit();
669+
}
670+
671+
module.glob_importers.borrow_mut().push(import);
672+
673+
for (binding, key, warn_ambiguity) in import_bindings {
674+
let _ = self.try_define_local(
675+
parent,
676+
key.ident.0,
677+
key.ns,
678+
binding,
679+
warn_ambiguity,
680+
);
681+
}
682+
683+
self.record_partial_res(*id, PartialRes::new(module.res().unwrap()));
684+
}
685+
686+
(_, SideEffectBindings::None) => {}
687+
688+
// Something weird happened, which shouldn't have happened.
689+
_ => unreachable!("Mismatched import kind and side effect"),
690+
}
687691
}
688692
}
689693

@@ -1000,7 +1004,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
10001004
_ => unreachable!(),
10011005
};
10021006

1003-
let mut import_bindings = bindings.clone().map(|b| b.get());
1007+
let mut import_bindings = PerNS::default();
10041008
let mut indeterminate_count = 0;
10051009
self.reborrow().per_ns_cm(|this, ns| {
10061010
if !type_ns_only || ns == TypeNS {
@@ -1018,12 +1022,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
10181022
Ok(binding) => {
10191023
// We need the `target`, `source` can be extracted.
10201024
let imported_binding = this.import(binding, import);
1021-
PendingBinding::Ready(Some(imported_binding))
1025+
Some(Some(imported_binding))
10221026
}
1023-
Err(Determinacy::Determined) => PendingBinding::Ready(None),
1027+
Err(Determinacy::Determined) => Some(None),
10241028
Err(Determinacy::Undetermined) => {
10251029
indeterminate_count += 1;
1026-
PendingBinding::Pending
1030+
None
10271031
}
10281032
};
10291033
import_bindings[ns] = pending_binding;
@@ -1595,34 +1599,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15951599
return SideEffectBindings::None;
15961600
}
15971601

1598-
// Ensure that `resolutions` isn't borrowed during `try_define`,
1599-
// since it might get updated via a glob cycle.
1600-
let bindings = self
1602+
let import_bindings = self
16011603
.resolutions(module)
16021604
.borrow()
16031605
.iter()
16041606
.filter_map(|(key, resolution)| {
1605-
resolution.borrow().binding().map(|binding| (*key, binding))
1607+
let binding = resolution.borrow().binding()?;
1608+
let mut key = *key;
1609+
let scope =
1610+
match key.ident.0.span.reverse_glob_adjust(module.expansion, import.span) {
1611+
Some(Some(def)) => self.expn_def_scope(def),
1612+
Some(None) => import.parent_scope.module,
1613+
None => return None,
1614+
};
1615+
self.is_accessible_from(binding.vis, scope).then(|| {
1616+
let imported_binding = self.import(binding, import);
1617+
let warn_ambiguity = self
1618+
.resolution(import.parent_scope.module, key)
1619+
.and_then(|r| r.binding())
1620+
.is_some_and(|binding| binding.warn_ambiguity_recursive());
1621+
(imported_binding, key, warn_ambiguity)
1622+
})
16061623
})
16071624
.collect::<Vec<_>>();
1608-
let mut import_bindings = Vec::with_capacity(bindings.len());
1609-
for (mut key, binding) in bindings {
1610-
let scope = match key.ident.0.span.reverse_glob_adjust(module.expansion, import.span) {
1611-
Some(Some(def)) => self.expn_def_scope(def),
1612-
Some(None) => import.parent_scope.module,
1613-
None => continue,
1614-
};
1615-
if self.is_accessible_from(binding.vis, scope) {
1616-
let imported_binding = self.import(binding, import);
1617-
let warn_ambiguity = self
1618-
.resolution(import.parent_scope.module, key)
1619-
.and_then(|r| r.binding())
1620-
.is_some_and(|binding| binding.warn_ambiguity_recursive());
1621-
import_bindings.push((imported_binding, key, warn_ambiguity));
1622-
}
1623-
}
16241625

1625-
// Record the destination of this import
16261626
SideEffectBindings::Glob { import_bindings }
16271627
}
16281628

0 commit comments

Comments
 (0)