Skip to content

Commit d80f558

Browse files
committed
resolve: Update NameBindingData::ambiguity in place
instead of creating fresh bindings, except in one case.
1 parent fa2e5ad commit d80f558

6 files changed

Lines changed: 59 additions & 41 deletions

File tree

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
8686
) {
8787
let binding = self.arenas.alloc_name_binding(NameBindingData {
8888
kind: NameBindingKind::Res(res),
89-
ambiguity,
89+
ambiguity: CmCell::new(ambiguity),
9090
// External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment.
9191
warn_ambiguity: CmCell::new(true),
9292
vis: CmCell::new(vis),

compiler/rustc_resolve/src/effective_visibilities.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
100100
if let Some(node_id) = import.id() {
101101
r.effective_visibilities.update_eff_vis(r.local_def_id(node_id), eff_vis, r.tcx)
102102
}
103-
} else if binding.ambiguity.is_some() && eff_vis.is_public_at_level(Level::Reexported) {
103+
} else if binding.ambiguity.get().is_some()
104+
&& eff_vis.is_public_at_level(Level::Reexported)
105+
{
104106
exported_ambiguities.insert(*binding);
105107
}
106108
}
@@ -126,7 +128,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
126128
// leading to it into the table. They are used by the `ambiguous_glob_reexports`
127129
// lint. For all bindings added to the table this way `is_ambiguity` returns true.
128130
let is_ambiguity =
129-
|binding: NameBinding<'ra>, warn: bool| binding.ambiguity.is_some() && !warn;
131+
|binding: NameBinding<'ra>, warn: bool| binding.ambiguity.get().is_some() && !warn;
130132
let mut parent_id = ParentId::Def(module_id);
131133
let mut warn_ambiguity = binding.warn_ambiguity.get();
132134
while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind {

compiler/rustc_resolve/src/imports.rs

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,10 @@ fn remove_same_import<'ra>(
305305
if let NameBindingKind::Import { import: import1, binding: b1_next } = b1.kind
306306
&& let NameBindingKind::Import { import: import2, binding: b2_next } = b2.kind
307307
&& import1 == import2
308-
&& b1.ambiguity == b2.ambiguity
308+
&& b1.warn_ambiguity.get() == b2.warn_ambiguity.get()
309309
{
310-
assert!(b1.ambiguity.is_none());
311-
assert_eq!(b1.warn_ambiguity.get(), b2.warn_ambiguity.get());
310+
assert_eq!(b1.ambiguity.get(), b2.ambiguity.get());
311+
assert!(!b1.warn_ambiguity.get());
312312
assert_eq!(b1.expansion, b2.expansion);
313313
assert_eq!(b1.span, b2.span);
314314
assert_eq!(b1.vis(), b2.vis());
@@ -344,7 +344,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
344344

345345
self.arenas.alloc_name_binding(NameBindingData {
346346
kind: NameBindingKind::Import { binding, import },
347-
ambiguity: None,
347+
ambiguity: CmCell::new(None),
348348
warn_ambiguity: CmCell::new(false),
349349
span: import.span,
350350
vis: CmCell::new(vis),
@@ -368,9 +368,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
368368
// all these overwrites will be re-fetched by glob imports importing
369369
// from that module without generating new ambiguities.
370370
// - A glob binding is overwritten by a non-glob binding arriving later.
371-
// - A glob binding is overwritten by an ambiguous glob binding.
372-
// FIXME: avoid this by putting `NameBindingData::ambiguity` under a
373-
// cell and updating it in place.
371+
// - A glob binding is overwritten by its clone after setting ambiguity in it.
372+
// FIXME: avoid this by removing `warn_ambiguity`, or by triggering glob re-fetch
373+
// with the same binding in some way.
374374
// - A glob binding is overwritten by a glob binding re-fetching an
375375
// overwritten binding from other module (the recursive case).
376376
// Here we are detecting all such re-fetches and overwrite old bindings
@@ -381,14 +381,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
381381
if deep_binding != glob_binding {
382382
// Some import layers have been removed, need to overwrite.
383383
assert_ne!(old_deep_binding, old_glob_binding);
384-
assert_ne!(old_deep_binding, deep_binding);
385-
assert!(old_deep_binding.is_glob_import());
384+
// FIXME: reenable the asserts when `warn_ambiguity` is removed (#149195).
385+
// assert_ne!(old_deep_binding, deep_binding);
386+
// assert!(old_deep_binding.is_glob_import());
387+
assert!(!deep_binding.is_glob_import());
386388
if glob_binding.is_ambiguity_recursive() {
387389
glob_binding.warn_ambiguity.set_unchecked(true);
388390
}
389391
glob_binding
390392
} else if glob_binding.res() != old_glob_binding.res() {
391-
self.new_ambiguity_binding(old_glob_binding, glob_binding, warn_ambiguity)
393+
old_glob_binding.ambiguity.set_unchecked(Some(glob_binding));
394+
old_glob_binding.warn_ambiguity.set_unchecked(warn_ambiguity);
395+
if warn_ambiguity {
396+
old_glob_binding
397+
} else {
398+
// Need a fresh binding so other glob imports importing it could re-fetch it
399+
// and set their own `warn_ambiguity` to true.
400+
// FIXME: remove this when `warn_ambiguity` is removed (#149195).
401+
self.arenas.alloc_name_binding((*old_glob_binding).clone())
402+
}
392403
} else if !old_glob_binding.vis().is_at_least(glob_binding.vis(), self.tcx) {
393404
// We are glob-importing the same item but with greater visibility.
394405
old_glob_binding.vis.set_unchecked(glob_binding.vis());
@@ -397,12 +408,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
397408
&& !old_glob_binding.is_ambiguity_recursive()
398409
{
399410
// Overwriting a non-ambiguous glob import with an ambiguous glob import.
400-
self.new_ambiguity_binding(
401-
AmbiguityKind::GlobVsGlob,
402-
old_glob_binding,
403-
glob_binding,
404-
true,
405-
)
411+
old_glob_binding.ambiguity.set_unchecked(Some(glob_binding));
412+
old_glob_binding.warn_ambiguity.set_unchecked(true);
413+
old_glob_binding
406414
} else {
407415
old_glob_binding
408416
}
@@ -430,6 +438,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
430438
self.update_local_resolution(module, key, warn_ambiguity, |this, resolution| {
431439
if let Some(old_binding) = resolution.best_binding() {
432440
assert_ne!(binding, old_binding);
441+
assert!(!binding.warn_ambiguity.get());
433442
if res == Res::Err && old_binding.res() != Res::Err {
434443
// Do not override real bindings with `Res::Err`s from error recovery.
435444
return Ok(());
@@ -471,19 +480,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
471480
})
472481
}
473482

474-
fn new_ambiguity_binding(
475-
&self,
476-
primary_binding: NameBinding<'ra>,
477-
secondary_binding: NameBinding<'ra>,
478-
warn_ambiguity: bool,
479-
) -> NameBinding<'ra> {
480-
let ambiguity = Some(secondary_binding);
481-
let warn_ambiguity = CmCell::new(warn_ambiguity);
482-
let vis = primary_binding.vis.clone();
483-
let data = NameBindingData { ambiguity, warn_ambiguity, vis, ..*primary_binding };
484-
self.arenas.alloc_name_binding(data)
485-
}
486-
487483
// Use `f` to mutate the resolution of the name in the module.
488484
// If the resolution becomes a success, define it in the module's glob importers.
489485
fn update_local_resolution<T, F>(
@@ -690,7 +686,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
690686
let Some(binding) = resolution.best_binding() else { continue };
691687

692688
if let NameBindingKind::Import { import, .. } = binding.kind
693-
&& let Some(amb_binding) = binding.ambiguity
689+
&& let Some(amb_binding) = binding.ambiguity.get()
694690
&& binding.res() != Res::Err
695691
&& exported_ambiguities.contains(&binding)
696692
{

compiler/rustc_resolve/src/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -804,10 +804,10 @@ impl<'ra> fmt::Debug for Module<'ra> {
804804
}
805805

806806
/// Records a possibly-private value, type, or module definition.
807-
#[derive(Debug)]
807+
#[derive(Clone, Debug)]
808808
struct NameBindingData<'ra> {
809809
kind: NameBindingKind<'ra>,
810-
ambiguity: Option<NameBinding<'ra>>,
810+
ambiguity: CmCell<Option<NameBinding<'ra>>>,
811811
/// Produce a warning instead of an error when reporting ambiguities inside this binding.
812812
/// May apply to indirect ambiguities under imports, so `ambiguity.is_some()` is not required.
813813
warn_ambiguity: CmCell<bool>,
@@ -942,7 +942,7 @@ impl<'ra> NameBindingData<'ra> {
942942
fn descent_to_ambiguity(
943943
self: NameBinding<'ra>,
944944
) -> Option<(NameBinding<'ra>, NameBinding<'ra>)> {
945-
match self.ambiguity {
945+
match self.ambiguity.get() {
946946
Some(ambig_binding) => Some((self, ambig_binding)),
947947
None => match self.kind {
948948
NameBindingKind::Import { binding, .. } => binding.descent_to_ambiguity(),
@@ -952,7 +952,7 @@ impl<'ra> NameBindingData<'ra> {
952952
}
953953

954954
fn is_ambiguity_recursive(&self) -> bool {
955-
self.ambiguity.is_some()
955+
self.ambiguity.get().is_some()
956956
|| match self.kind {
957957
NameBindingKind::Import { binding, .. } => binding.is_ambiguity_recursive(),
958958
_ => false,
@@ -1351,7 +1351,7 @@ impl<'ra> ResolverArenas<'ra> {
13511351
) -> NameBinding<'ra> {
13521352
self.alloc_name_binding(NameBindingData {
13531353
kind: NameBindingKind::Res(res),
1354-
ambiguity: None,
1354+
ambiguity: CmCell::new(None),
13551355
warn_ambiguity: CmCell::new(false),
13561356
vis: CmCell::new(vis),
13571357
span,
@@ -2068,7 +2068,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
20682068
used: Used,
20692069
warn_ambiguity: bool,
20702070
) {
2071-
if let Some(b2) = used_binding.ambiguity {
2071+
if let Some(b2) = used_binding.ambiguity.get() {
20722072
let ambiguity_error = AmbiguityError {
20732073
kind: AmbiguityKind::GlobVsGlob,
20742074
ident,

tests/ui/imports/issue-55884-1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ mod m {
1717

1818
fn main() {
1919
use m::S; //~ ERROR `S` is ambiguous
20-
let s = S {};
20+
let s = S {}; //~ ERROR `S` is ambiguous
2121
}

tests/ui/imports/issue-55884-1.stderr

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@ LL | pub use self::m2::*;
1818
| ^^^^^^^^^^^
1919
= help: consider adding an explicit import of `S` to disambiguate
2020

21-
error: aborting due to 1 previous error
21+
error[E0659]: `S` is ambiguous
22+
--> $DIR/issue-55884-1.rs:20:13
23+
|
24+
LL | let s = S {};
25+
| ^ ambiguous name
26+
|
27+
= note: ambiguous because of multiple glob imports of a name in the same module
28+
note: `S` could refer to the struct imported here
29+
--> $DIR/issue-55884-1.rs:14:13
30+
|
31+
LL | pub use self::m1::*;
32+
| ^^^^^^^^^^^
33+
= help: consider adding an explicit import of `S` to disambiguate
34+
note: `S` could also refer to the struct imported here
35+
--> $DIR/issue-55884-1.rs:15:13
36+
|
37+
LL | pub use self::m2::*;
38+
| ^^^^^^^^^^^
39+
= help: consider adding an explicit import of `S` to disambiguate
40+
41+
error: aborting due to 2 previous errors
2242

2343
For more information about this error, try `rustc --explain E0659`.

0 commit comments

Comments
 (0)