Skip to content

Commit a251ae2

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

6 files changed

Lines changed: 60 additions & 36 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
@@ -89,7 +89,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
8989
) {
9090
let decl = self.arenas.alloc_decl(DeclData {
9191
kind: DeclKind::Def(res),
92-
ambiguity,
92+
ambiguity: CmCell::new(ambiguity),
9393
// External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment.
9494
warn_ambiguity: CmCell::new(true),
9595
vis: CmCell::new(vis),

compiler/rustc_resolve/src/effective_visibilities.rs

Lines changed: 5 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 decl.ambiguity.is_some() && eff_vis.is_public_at_level(Level::Reexported) {
103+
} else if decl.ambiguity.get().is_some()
104+
&& eff_vis.is_public_at_level(Level::Reexported)
105+
{
104106
exported_ambiguities.insert(*decl);
105107
}
106108
}
@@ -125,7 +127,8 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
125127
// If the binding is ambiguous, put the root ambiguity binding and all reexports
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.
128-
let is_ambiguity = |decl: Decl<'ra>, warn: bool| decl.ambiguity.is_some() && !warn;
130+
let is_ambiguity =
131+
|decl: Decl<'ra>, warn: bool| decl.ambiguity.get().is_some() && !warn;
129132
let mut parent_id = ParentId::Def(module_id);
130133
let mut warn_ambiguity = decl.warn_ambiguity.get();
131134
while let DeclKind::Import { source_decl, .. } = decl.kind {

compiler/rustc_resolve/src/imports.rs

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,10 @@ fn remove_same_import<'ra>(d1: Decl<'ra>, d2: Decl<'ra>) -> (Decl<'ra>, Decl<'ra
300300
if let DeclKind::Import { import: import1, source_decl: d1_next } = d1.kind
301301
&& let DeclKind::Import { import: import2, source_decl: d2_next } = d2.kind
302302
&& import1 == import2
303-
&& d1.ambiguity == d2.ambiguity
303+
&& d1.warn_ambiguity.get() == d2.warn_ambiguity.get()
304304
{
305-
assert!(d1.ambiguity.is_none());
306-
assert_eq!(d1.warn_ambiguity.get(), d2.warn_ambiguity.get());
305+
assert_eq!(d1.ambiguity.get(), d2.ambiguity.get());
306+
assert!(!d1.warn_ambiguity.get());
307307
assert_eq!(d1.expansion, d2.expansion);
308308
assert_eq!(d1.span, d2.span);
309309
assert_eq!(d1.vis(), d2.vis());
@@ -335,7 +335,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
335335

336336
self.arenas.alloc_decl(DeclData {
337337
kind: DeclKind::Import { source_decl: decl, import },
338-
ambiguity: None,
338+
ambiguity: CmCell::new(None),
339339
warn_ambiguity: CmCell::new(false),
340340
span: import.span,
341341
vis: CmCell::new(vis),
@@ -359,9 +359,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
359359
// all these overwrites will be re-fetched by glob imports importing
360360
// from that module without generating new ambiguities.
361361
// - A glob decl is overwritten by a non-glob decl arriving later.
362-
// - A glob decl is overwritten by an ambiguous glob decl.
363-
// FIXME: avoid this by putting `DeclData::ambiguity` under a
364-
// cell and updating it in place.
362+
// - A glob decl is overwritten by its clone after setting ambiguity in it.
363+
// FIXME: avoid this by removing `warn_ambiguity`, or by triggering glob re-fetch
364+
// with the same decl in some way.
365365
// - A glob decl is overwritten by a glob decl re-fetching an
366366
// overwritten decl from other module (the recursive case).
367367
// Here we are detecting all such re-fetches and overwrite old decls
@@ -372,21 +372,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
372372
if deep_decl != glob_decl {
373373
// Some import layers have been removed, need to overwrite.
374374
assert_ne!(old_deep_decl, old_glob_decl);
375-
assert_ne!(old_deep_decl, deep_decl);
376-
assert!(old_deep_decl.is_glob_import());
375+
// FIXME: reenable the asserts when `warn_ambiguity` is removed (#149195).
376+
// assert_ne!(old_deep_decl, deep_decl);
377+
// assert!(old_deep_decl.is_glob_import());
378+
assert!(!deep_decl.is_glob_import());
377379
if glob_decl.is_ambiguity_recursive() {
378380
glob_decl.warn_ambiguity.set_unchecked(true);
379381
}
380382
glob_decl
381383
} else if glob_decl.res() != old_glob_decl.res() {
382-
self.new_decl_with_ambiguity(old_glob_decl, glob_decl, warn_ambiguity)
384+
old_glob_decl.ambiguity.set_unchecked(Some(glob_decl));
385+
old_glob_decl.warn_ambiguity.set_unchecked(warn_ambiguity);
386+
if warn_ambiguity {
387+
old_glob_decl
388+
} else {
389+
// Need a fresh decl so other glob imports importing it could re-fetch it
390+
// and set their own `warn_ambiguity` to true.
391+
// FIXME: remove this when `warn_ambiguity` is removed (#149195).
392+
self.arenas.alloc_decl((*old_glob_decl).clone())
393+
}
383394
} else if !old_glob_decl.vis().is_at_least(glob_decl.vis(), self.tcx) {
384395
// We are glob-importing the same item but with greater visibility.
385396
old_glob_decl.vis.set_unchecked(glob_decl.vis());
386397
old_glob_decl
387398
} else if glob_decl.is_ambiguity_recursive() && !old_glob_decl.is_ambiguity_recursive() {
388399
// Overwriting a non-ambiguous glob import with an ambiguous glob import.
389-
self.new_decl_with_ambiguity(old_glob_decl, glob_decl, true)
400+
old_glob_decl.ambiguity.set_unchecked(Some(glob_decl));
401+
old_glob_decl.warn_ambiguity.set_unchecked(true);
402+
old_glob_decl
390403
} else {
391404
old_glob_decl
392405
}
@@ -415,6 +428,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
415428
self.update_local_resolution(module, key, warn_ambiguity, |this, resolution| {
416429
if let Some(old_decl) = resolution.best_decl() {
417430
assert_ne!(decl, old_decl);
431+
assert!(!decl.warn_ambiguity.get());
418432
if res == Res::Err && old_decl.res() != Res::Err {
419433
// Do not override real declarations with `Res::Err`s from error recovery.
420434
return Ok(());
@@ -453,19 +467,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
453467
})
454468
}
455469

456-
fn new_decl_with_ambiguity(
457-
&self,
458-
primary_decl: Decl<'ra>,
459-
secondary_decl: Decl<'ra>,
460-
warn_ambiguity: bool,
461-
) -> Decl<'ra> {
462-
let ambiguity = Some(secondary_decl);
463-
let warn_ambiguity = CmCell::new(warn_ambiguity);
464-
let vis = primary_decl.vis.clone();
465-
let data = DeclData { ambiguity, warn_ambiguity, vis, ..*primary_decl };
466-
self.arenas.alloc_decl(data)
467-
}
468-
469470
// Use `f` to mutate the resolution of the name in the module.
470471
// If the resolution becomes a success, define it in the module's glob importers.
471472
fn update_local_resolution<T, F>(
@@ -671,7 +672,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
671672
let Some(binding) = resolution.best_decl() else { continue };
672673

673674
if let DeclKind::Import { import, .. } = binding.kind
674-
&& let Some(amb_binding) = binding.ambiguity
675+
&& let Some(amb_binding) = binding.ambiguity.get()
675676
&& binding.res() != Res::Err
676677
&& exported_ambiguities.contains(&binding)
677678
{

compiler/rustc_resolve/src/lib.rs

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

804804
/// Data associated with any name declaration.
805-
#[derive(Debug)]
805+
#[derive(Clone, Debug)]
806806
struct DeclData<'ra> {
807807
kind: DeclKind<'ra>,
808-
ambiguity: Option<Decl<'ra>>,
808+
ambiguity: CmCell<Option<Decl<'ra>>>,
809809
/// Produce a warning instead of an error when reporting ambiguities inside this binding.
810810
/// May apply to indirect ambiguities under imports, so `ambiguity.is_some()` is not required.
811811
warn_ambiguity: CmCell<bool>,
@@ -942,7 +942,7 @@ impl<'ra> DeclData<'ra> {
942942
}
943943

944944
fn descent_to_ambiguity(self: Decl<'ra>) -> Option<(Decl<'ra>, Decl<'ra>)> {
945-
match self.ambiguity {
945+
match self.ambiguity.get() {
946946
Some(ambig_binding) => Some((self, ambig_binding)),
947947
None => match self.kind {
948948
DeclKind::Import { source_decl, .. } => source_decl.descent_to_ambiguity(),
@@ -952,7 +952,7 @@ impl<'ra> DeclData<'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
DeclKind::Import { source_decl, .. } => source_decl.is_ambiguity_recursive(),
958958
_ => false,
@@ -1346,7 +1346,7 @@ impl<'ra> ResolverArenas<'ra> {
13461346
) -> Decl<'ra> {
13471347
self.alloc_decl(DeclData {
13481348
kind: DeclKind::Def(res),
1349-
ambiguity: None,
1349+
ambiguity: CmCell::new(None),
13501350
warn_ambiguity: CmCell::new(false),
13511351
vis: CmCell::new(vis),
13521352
span,
@@ -2055,7 +2055,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
20552055
used: Used,
20562056
warn_ambiguity: bool,
20572057
) {
2058-
if let Some(b2) = used_decl.ambiguity {
2058+
if let Some(b2) = used_decl.ambiguity.get() {
20592059
let ambiguity_error = AmbiguityError {
20602060
kind: AmbiguityKind::GlobVsGlob,
20612061
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)