Skip to content

Commit ec57a75

Browse files
committed
resolve: Partially convert ambiguous_glob_imports lint into a hard error
1 parent d0835ad commit ec57a75

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+221
-841
lines changed

compiler/rustc_codegen_gcc/build_system/src/test.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -826,8 +826,6 @@ fn valid_ui_error_pattern_test(file: &str) -> bool {
826826
"type-alias-impl-trait/auxiliary/cross_crate_ice.rs",
827827
"type-alias-impl-trait/auxiliary/cross_crate_ice2.rs",
828828
"macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs",
829-
"imports/ambiguous-1.rs",
830-
"imports/ambiguous-4-extern.rs",
831829
"entry-point/auxiliary/bad_main_functions.rs",
832830
]
833831
.iter()

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4436,7 +4436,7 @@ declare_lint! {
44364436
///
44374437
/// ### Example
44384438
///
4439-
/// ```rust,compile_fail
4439+
/// ```rust,ignore (needs extern crate)
44404440
/// #![deny(ambiguous_glob_imports)]
44414441
/// pub fn foo() -> u32 {
44424442
/// use sub::*;
@@ -4452,8 +4452,6 @@ declare_lint! {
44524452
/// }
44534453
/// ```
44544454
///
4455-
/// {{produces}}
4456-
///
44574455
/// ### Explanation
44584456
///
44594457
/// Previous versions of Rust compile it successfully because it

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
5353
ns: Namespace,
5454
binding: NameBinding<'ra>,
5555
) {
56-
if let Err(old_binding) = self.try_define_local(parent, ident, ns, binding, false) {
56+
if let Err(old_binding) = self.try_define_local(parent, ident, ns, binding) {
5757
self.report_conflict(parent, ident, ns, old_binding, binding);
5858
}
5959
}
@@ -82,13 +82,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
8282
vis: Visibility<DefId>,
8383
span: Span,
8484
expansion: LocalExpnId,
85-
ambiguity: Option<(NameBinding<'ra>, AmbiguityKind)>,
85+
ambiguity: Option<(NameBinding<'ra>, AmbiguityKind, bool)>,
8686
) {
8787
let binding = self.arenas.alloc_name_binding(NameBindingData {
8888
kind: NameBindingKind::Res(res),
8989
ambiguity,
90-
// External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment.
91-
warn_ambiguity: true,
9290
vis,
9391
span,
9492
expansion,
@@ -288,7 +286,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
288286
AmbigModChildKind::GlobVsGlob => AmbiguityKind::GlobVsGlob,
289287
AmbigModChildKind::GlobVsExpanded => AmbiguityKind::GlobVsExpanded,
290288
};
291-
(self.arenas.new_res_binding(res, vis, span, expansion), ambig_kind)
289+
// External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment.
290+
(self.arenas.new_res_binding(res, vis, span, expansion), ambig_kind, true)
292291
});
293292

294293
// Record primary definitions.

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,6 +1995,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
19951995
}
19961996
}
19971997

1998+
pub(crate) fn remove_same_import(
1999+
b1: NameBinding<'ra>,
2000+
b2: NameBinding<'ra>,
2001+
) -> (NameBinding<'ra>, NameBinding<'ra>) {
2002+
if let NameBindingKind::Import { import: import1, binding: b1_next } = b1.kind
2003+
&& let NameBindingKind::Import { import: import2, binding: b2_next } = b2.kind
2004+
&& import1 == import2
2005+
&& b1.ambiguity == b2.ambiguity
2006+
{
2007+
assert!(b1.ambiguity.is_none());
2008+
assert_eq!(b1.expansion, b2.expansion);
2009+
assert_eq!(b1.span, b2.span);
2010+
assert_eq!(b1.vis, b2.vis);
2011+
Self::remove_same_import(b1_next, b2_next)
2012+
} else {
2013+
(b1, b2)
2014+
}
2015+
}
2016+
19982017
fn ambiguity_diagnostic(&self, ambiguity_error: &AmbiguityError<'ra>) -> errors::Ambiguity {
19992018
let AmbiguityError { kind, ident, b1, b2, misc1, misc2, .. } = *ambiguity_error;
20002019
let extern_prelude_ambiguity = || {
@@ -2003,6 +2022,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
20032022
&& entry.flag_binding.as_ref().and_then(|pb| pb.get().0.binding()) == Some(b2)
20042023
})
20052024
};
2025+
let (b1, b2) = Self::remove_same_import(b1, b2);
20062026
let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
20072027
// We have to print the span-less alternative first, otherwise formatting looks bad.
20082028
(b2, b1, misc2, misc1, true)

compiler/rustc_resolve/src/effective_visibilities.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -125,27 +125,13 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
125125
// If the binding is ambiguous, put the root ambiguity binding and all reexports
126126
// leading to it into the table. They are used by the `ambiguous_glob_reexports`
127127
// lint. For all bindings added to the table this way `is_ambiguity` returns true.
128-
let is_ambiguity =
129-
|binding: NameBinding<'ra>, warn: bool| binding.ambiguity.is_some() && !warn;
130128
let mut parent_id = ParentId::Def(module_id);
131-
let mut warn_ambiguity = binding.warn_ambiguity;
132129
while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind {
133130
self.update_import(binding, parent_id);
134-
135-
if is_ambiguity(binding, warn_ambiguity) {
136-
// Stop at the root ambiguity, further bindings in the chain should not
137-
// be reexported because the root ambiguity blocks any access to them.
138-
// (Those further bindings are most likely not ambiguities themselves.)
139-
break;
140-
}
141-
142131
parent_id = ParentId::Import(binding);
143132
binding = nested_binding;
144-
warn_ambiguity |= nested_binding.warn_ambiguity;
145133
}
146-
if !is_ambiguity(binding, warn_ambiguity)
147-
&& let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local())
148-
{
134+
if let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) {
149135
self.update_def(def_id, binding.vis.expect_local(), parent_id);
150136
}
151137
}

compiler/rustc_resolve/src/imports.rs

Lines changed: 67 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -325,21 +325,68 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
325325
self.arenas.alloc_name_binding(NameBindingData {
326326
kind: NameBindingKind::Import { binding, import },
327327
ambiguity: None,
328-
warn_ambiguity: false,
329328
span: import.span,
330329
vis,
331330
expansion: import.parent_scope.expansion,
332331
})
333332
}
334333

334+
fn select_glob_binding(
335+
&self,
336+
glob_binding: NameBinding<'ra>,
337+
old_glob_binding: NameBinding<'ra>,
338+
) -> NameBinding<'ra> {
339+
assert!(glob_binding.is_glob_import());
340+
assert!(old_glob_binding.is_glob_import());
341+
assert_ne!(glob_binding, old_glob_binding);
342+
// `best_binding` with a given key in a module may be overwritten in a
343+
// number of cases (all of them can be seen below in this `match`),
344+
// all these overwrites will be re-fetched by glob imports importing
345+
// from that module without generating new ambiguities.
346+
// - A glob binding is overwritten by a non-glob binding arriving later.
347+
// - A glob binding is overwritten by an ambiguous glob binding.
348+
// FIXME: avoid this by putting `NameBindingData::ambiguity` under a
349+
// cell and updating it in place.
350+
// - A glob binding is overwritten by a glob binding with larger visibility.
351+
// FIXME: avoid this by putting `NameBindingData::vis` under a cell
352+
// and updating it in place.
353+
// - A glob binding is overwritten by a glob binding re-fetching an
354+
// overwritten binding from other module (the recursive case).
355+
// Here we are detecting all such re-fetches and overwrite old bindings
356+
// with the re-fetched bindings.
357+
let (deep_binding, old_deep_binding) =
358+
Self::remove_same_import(glob_binding, old_glob_binding);
359+
if deep_binding != glob_binding {
360+
assert_ne!(old_deep_binding, old_glob_binding);
361+
assert_ne!(old_deep_binding, deep_binding);
362+
assert!(old_deep_binding.is_glob_import());
363+
assert!(old_deep_binding.ambiguity.is_none());
364+
glob_binding
365+
} else if glob_binding.res() != old_glob_binding.res() {
366+
self.new_ambiguity_binding(
367+
AmbiguityKind::GlobVsGlob,
368+
old_glob_binding,
369+
glob_binding,
370+
false,
371+
)
372+
} else if !old_glob_binding.vis.is_at_least(glob_binding.vis, self.tcx)
373+
|| glob_binding.is_ambiguity_recursive()
374+
{
375+
// We are glob-importing the same item but with greater visibility,
376+
// or overwriting with an ambiguous glob import.
377+
glob_binding
378+
} else {
379+
old_glob_binding
380+
}
381+
}
382+
335383
/// Define the name or return the existing binding if there is a collision.
336384
pub(crate) fn try_define_local(
337385
&mut self,
338386
module: Module<'ra>,
339387
ident: Ident,
340388
ns: Namespace,
341389
binding: NameBinding<'ra>,
342-
warn_ambiguity: bool,
343390
) -> Result<(), NameBinding<'ra>> {
344391
let res = binding.res();
345392
self.check_reserved_macro_name(ident, res);
@@ -351,40 +398,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
351398
module.underscore_disambiguator.update_unchecked(|d| d + 1);
352399
module.underscore_disambiguator.get()
353400
});
354-
self.update_local_resolution(module, key, warn_ambiguity, |this, resolution| {
401+
self.update_local_resolution(module, key, |this, resolution| {
355402
if let Some(old_binding) = resolution.best_binding() {
403+
assert_ne!(binding, old_binding);
356404
if res == Res::Err && old_binding.res() != Res::Err {
357405
// Do not override real bindings with `Res::Err`s from error recovery.
358406
return Ok(());
359407
}
360408
match (old_binding.is_glob_import(), binding.is_glob_import()) {
361409
(true, true) => {
362-
let (glob_binding, old_glob_binding) = (binding, old_binding);
363-
// FIXME: remove `!binding.is_ambiguity_recursive()` after delete the warning ambiguity.
364-
if !binding.is_ambiguity_recursive()
365-
&& let NameBindingKind::Import { import: old_import, .. } =
366-
old_glob_binding.kind
367-
&& let NameBindingKind::Import { import, .. } = glob_binding.kind
368-
&& old_import == import
369-
{
370-
// When imported from the same glob-import statement, we should replace
371-
// `old_glob_binding` with `glob_binding`, regardless of whether
372-
// they have the same resolution or not.
373-
resolution.glob_binding = Some(glob_binding);
374-
} else if res != old_glob_binding.res() {
375-
resolution.glob_binding = Some(this.new_ambiguity_binding(
376-
AmbiguityKind::GlobVsGlob,
377-
old_glob_binding,
378-
glob_binding,
379-
warn_ambiguity,
380-
));
381-
} else if !old_binding.vis.is_at_least(binding.vis, this.tcx) {
382-
// We are glob-importing the same item but with greater visibility.
383-
resolution.glob_binding = Some(glob_binding);
384-
} else if binding.is_ambiguity_recursive() {
385-
resolution.glob_binding =
386-
Some(this.new_warn_ambiguity_binding(glob_binding));
387-
}
410+
resolution.glob_binding =
411+
Some(this.select_glob_binding(binding, old_binding))
388412
}
389413
(old_glob @ true, false) | (old_glob @ false, true) => {
390414
let (glob_binding, non_glob_binding) =
@@ -403,18 +427,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
403427
resolution.non_glob_binding = Some(non_glob_binding);
404428
}
405429

406-
if let Some(old_glob_binding) = resolution.glob_binding {
407-
assert!(old_glob_binding.is_glob_import());
408-
if glob_binding.res() != old_glob_binding.res() {
409-
resolution.glob_binding = Some(this.new_ambiguity_binding(
410-
AmbiguityKind::GlobVsGlob,
411-
old_glob_binding,
412-
glob_binding,
413-
false,
414-
));
415-
} else if !old_glob_binding.vis.is_at_least(binding.vis, this.tcx) {
416-
resolution.glob_binding = Some(glob_binding);
417-
}
430+
if let Some(old_glob_binding) = resolution.glob_binding
431+
&& old_glob_binding != glob_binding
432+
{
433+
resolution.glob_binding =
434+
Some(this.select_glob_binding(glob_binding, old_glob_binding));
418435
} else {
419436
resolution.glob_binding = Some(glob_binding);
420437
}
@@ -440,33 +457,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
440457
ambiguity_kind: AmbiguityKind,
441458
primary_binding: NameBinding<'ra>,
442459
secondary_binding: NameBinding<'ra>,
443-
warn_ambiguity: bool,
460+
warning: bool,
444461
) -> NameBinding<'ra> {
445-
let ambiguity = Some((secondary_binding, ambiguity_kind));
446-
let data = NameBindingData { ambiguity, warn_ambiguity, ..*primary_binding };
462+
let ambiguity = Some((secondary_binding, ambiguity_kind, warning));
463+
let data = NameBindingData { ambiguity, ..*primary_binding };
447464
self.arenas.alloc_name_binding(data)
448465
}
449466

450-
fn new_warn_ambiguity_binding(&self, binding: NameBinding<'ra>) -> NameBinding<'ra> {
451-
assert!(binding.is_ambiguity_recursive());
452-
self.arenas.alloc_name_binding(NameBindingData { warn_ambiguity: true, ..*binding })
453-
}
454-
455467
// Use `f` to mutate the resolution of the name in the module.
456468
// If the resolution becomes a success, define it in the module's glob importers.
457-
fn update_local_resolution<T, F>(
458-
&mut self,
459-
module: Module<'ra>,
460-
key: BindingKey,
461-
warn_ambiguity: bool,
462-
f: F,
463-
) -> T
469+
fn update_local_resolution<T, F>(&mut self, module: Module<'ra>, key: BindingKey, f: F) -> T
464470
where
465471
F: FnOnce(&Resolver<'ra, 'tcx>, &mut NameResolution<'ra>) -> T,
466472
{
467473
// Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
468474
// during which the resolution might end up getting re-defined via a glob cycle.
469-
let (binding, t, warn_ambiguity) = {
475+
let (binding, t) = {
470476
let resolution = &mut *self.resolution_or_default(module, key).borrow_mut_unchecked();
471477
let old_binding = resolution.binding();
472478

@@ -475,7 +481,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
475481
if let Some(binding) = resolution.binding()
476482
&& old_binding != Some(binding)
477483
{
478-
(binding, t, warn_ambiguity || old_binding.is_some())
484+
(binding, t)
479485
} else {
480486
return t;
481487
}
@@ -500,7 +506,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
500506
ident.0,
501507
key.ns,
502508
imported_binding,
503-
warn_ambiguity,
504509
);
505510
}
506511
}
@@ -521,11 +526,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
521526
let dummy_binding = self.import(dummy_binding, import);
522527
self.per_ns(|this, ns| {
523528
let module = import.parent_scope.module;
524-
let _ = this.try_define_local(module, target, ns, dummy_binding, false);
529+
let _ = this.try_define_local(module, target, ns, dummy_binding);
525530
// Don't remove underscores from `single_imports`, they were never added.
526531
if target.name != kw::Underscore {
527532
let key = BindingKey::new(target, ns);
528-
this.update_local_resolution(module, key, false, |_, resolution| {
533+
this.update_local_resolution(module, key, |_, resolution| {
529534
resolution.single_imports.swap_remove(&import);
530535
})
531536
}
@@ -658,7 +663,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
658663
let Some(binding) = resolution.best_binding() else { continue };
659664

660665
if let NameBindingKind::Import { import, .. } = binding.kind
661-
&& let Some((amb_binding, _)) = binding.ambiguity
666+
&& let Some((amb_binding, ..)) = binding.ambiguity
662667
&& binding.res() != Res::Err
663668
&& exported_ambiguities.contains(&binding)
664669
{
@@ -917,7 +922,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
917922
this.get_mut_unchecked().update_local_resolution(
918923
parent,
919924
key,
920-
false,
921925
|_, resolution| {
922926
resolution.single_imports.swap_remove(&import);
923927
},
@@ -1523,16 +1527,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15231527
};
15241528
if self.is_accessible_from(binding.vis, scope) {
15251529
let imported_binding = self.import(binding, import);
1526-
let warn_ambiguity = self
1527-
.resolution(import.parent_scope.module, key)
1528-
.and_then(|r| r.binding())
1529-
.is_some_and(|binding| binding.warn_ambiguity_recursive());
15301530
let _ = self.try_define_local(
15311531
import.parent_scope.module,
15321532
key.ident.0,
15331533
key.ns,
15341534
imported_binding,
1535-
warn_ambiguity,
15361535
);
15371536
}
15381537
}

0 commit comments

Comments
 (0)