Skip to content

Commit a8be4d2

Browse files
address review
1 parent 1dec116 commit a8be4d2

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]
@@ -656,11 +561,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
656561

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

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

@@ -997,7 +1001,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
9971001
_ => unreachable!(),
9981002
};
9991003

1000-
let mut import_bindings = bindings.clone().map(|b| b.get());
1004+
let mut import_bindings = PerNS::default();
10011005
let mut indeterminate_count = 0;
10021006
self.reborrow().per_ns_cm(|this, ns| {
10031007
if !type_ns_only || ns == TypeNS {
@@ -1015,12 +1019,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
10151019
Ok(binding) => {
10161020
// We need the `target`, `source` can be extracted.
10171021
let imported_binding = this.import(binding, import);
1018-
PendingBinding::Ready(Some(imported_binding))
1022+
Some(Some(imported_binding))
10191023
}
1020-
Err(Determinacy::Determined) => PendingBinding::Ready(None),
1024+
Err(Determinacy::Determined) => Some(None),
10211025
Err(Determinacy::Undetermined) => {
10221026
indeterminate_count += 1;
1023-
PendingBinding::Pending
1027+
None
10241028
}
10251029
};
10261030
import_bindings[ns] = pending_binding;
@@ -1589,34 +1593,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15891593
return SideEffectBindings::None;
15901594
}
15911595

1592-
// Ensure that `resolutions` isn't borrowed during `try_define`,
1593-
// since it might get updated via a glob cycle.
1594-
let bindings = self
1596+
let import_bindings = self
15951597
.resolutions(module)
15961598
.borrow()
15971599
.iter()
15981600
.filter_map(|(key, resolution)| {
1599-
resolution.borrow().binding().map(|binding| (*key, binding))
1601+
let binding = resolution.borrow().binding()?;
1602+
let mut key = *key;
1603+
let scope =
1604+
match key.ident.0.span.reverse_glob_adjust(module.expansion, import.span) {
1605+
Some(Some(def)) => self.expn_def_scope(def),
1606+
Some(None) => import.parent_scope.module,
1607+
None => return None,
1608+
};
1609+
self.is_accessible_from(binding.vis, scope).then(|| {
1610+
let imported_binding = self.import(binding, import);
1611+
let warn_ambiguity = self
1612+
.resolution(import.parent_scope.module, key)
1613+
.and_then(|r| r.binding())
1614+
.is_some_and(|binding| binding.warn_ambiguity_recursive());
1615+
(imported_binding, key, warn_ambiguity)
1616+
})
16001617
})
16011618
.collect::<Vec<_>>();
1602-
let mut import_bindings = Vec::with_capacity(bindings.len());
1603-
for (mut key, binding) in bindings {
1604-
let scope = match key.ident.0.span.reverse_glob_adjust(module.expansion, import.span) {
1605-
Some(Some(def)) => self.expn_def_scope(def),
1606-
Some(None) => import.parent_scope.module,
1607-
None => continue,
1608-
};
1609-
if self.is_accessible_from(binding.vis, scope) {
1610-
let imported_binding = self.import(binding, import);
1611-
let warn_ambiguity = self
1612-
.resolution(import.parent_scope.module, key)
1613-
.and_then(|r| r.binding())
1614-
.is_some_and(|binding| binding.warn_ambiguity_recursive());
1615-
import_bindings.push((imported_binding, key, warn_ambiguity));
1616-
}
1617-
}
16181619

1619-
// Record the destination of this import
16201620
SideEffectBindings::Glob { import_bindings }
16211621
}
16221622

0 commit comments

Comments
 (0)