Skip to content

Commit df1b9bf

Browse files
committed
Auto merge of #149195 - petrochenkov:globamberr, r=<try>
resolve: Partially convert `ambiguous_glob_imports` lint into a hard error
2 parents 80b8982 + 42c3c67 commit df1b9bf

40 files changed

Lines changed: 227 additions & 848 deletions

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
@@ -4438,7 +4438,7 @@ declare_lint! {
44384438
///
44394439
/// ### Example
44404440
///
4441-
/// ```rust,compile_fail
4441+
/// ```rust,ignore (needs extern crate)
44424442
/// #![deny(ambiguous_glob_imports)]
44434443
/// pub fn foo() -> u32 {
44444444
/// use sub::*;
@@ -4454,8 +4454,6 @@ declare_lint! {
44544454
/// }
44554455
/// ```
44564456
///
4457-
/// {{produces}}
4458-
///
44594457
/// ### Explanation
44604458
///
44614459
/// 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
@@ -54,7 +54,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
5454
decl: Decl<'ra>,
5555
) {
5656
if let Err(old_decl) =
57-
self.try_plant_decl_into_local_module(ident, orig_ident_span, ns, decl, false)
57+
self.try_plant_decl_into_local_module(ident, orig_ident_span, ns, decl)
5858
{
5959
self.report_conflict(ident, ns, old_decl, decl);
6060
}
@@ -88,13 +88,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
8888
vis: Visibility<DefId>,
8989
span: Span,
9090
expansion: LocalExpnId,
91-
ambiguity: Option<Decl<'ra>>,
91+
ambiguity: Option<(Decl<'ra>, bool)>,
9292
) {
9393
let decl = self.arenas.alloc_decl(DeclData {
9494
kind: DeclKind::Def(res),
9595
ambiguity: CmCell::new(ambiguity),
96-
// External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment.
97-
warn_ambiguity: CmCell::new(true),
9896
vis: CmCell::new(vis),
9997
span,
10098
expansion,
@@ -292,7 +290,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
292290
let ModChild { ident: _, res, vis, ref reexport_chain } = *ambig_child;
293291
let span = child_span(self, reexport_chain, res);
294292
let res = res.expect_non_local();
295-
self.arenas.new_def_decl(res, vis, span, expansion, Some(parent))
293+
// External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment.
294+
(self.arenas.new_def_decl(res, vis, span, expansion, Some(parent)), true)
296295
});
297296

298297
// Record primary definitions.

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
11251125
.emit()
11261126
}
11271127

1128-
fn def_path_str(&self, mut def_id: DefId) -> String {
1128+
pub(crate) fn def_path_str(&self, mut def_id: DefId) -> String {
11291129
// We can't use `def_path_str` in resolve.
11301130
let mut path = vec![def_id];
11311131
while let Some(parent) = self.tcx.opt_parent(def_id) {

compiler/rustc_resolve/src/imports.rs

Lines changed: 84 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,6 @@ fn remove_same_import<'ra>(d1: Decl<'ra>, d2: Decl<'ra>) -> (Decl<'ra>, Decl<'ra
314314
}
315315
// Visibility of the new import declaration may be different,
316316
// because it already incorporates the visibility of the source binding.
317-
// `warn_ambiguity` of a re-fetched glob can also change in both directions.
318317
remove_same_import(d1_next, d2_next)
319318
} else {
320319
(d1, d2)
@@ -344,22 +343,50 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
344343
self.arenas.alloc_decl(DeclData {
345344
kind: DeclKind::Import { source_decl: decl, import },
346345
ambiguity: CmCell::new(None),
347-
warn_ambiguity: CmCell::new(false),
348346
span: import.span,
349347
vis: CmCell::new(vis),
350348
expansion: import.parent_scope.expansion,
351349
parent_module: Some(import.parent_scope.module),
352350
})
353351
}
354352

353+
fn is_noise_0_7_0(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> bool {
354+
let DeclKind::Import { import: i1, .. } = glob_decl.kind else { unreachable!() };
355+
let DeclKind::Import { import: i2, .. } = old_glob_decl.kind else { unreachable!() };
356+
let [seg1, seg2] = &i1.module_path[..] else { return false };
357+
if seg1.ident.name != kw::SelfLower || seg2.ident.name.as_str() != "perlin_surflet" {
358+
return false;
359+
}
360+
let [seg1, seg2] = &i2.module_path[..] else { return false };
361+
if seg1.ident.name != kw::SelfLower || seg2.ident.name.as_str() != "perlin" {
362+
return false;
363+
}
364+
let Some(def_id1) = glob_decl.res().opt_def_id() else { return false };
365+
let Some(def_id2) = old_glob_decl.res().opt_def_id() else { return false };
366+
self.def_path_str(def_id1).ends_with("noise_fns::generators::perlin_surflet::Perlin")
367+
&& self.def_path_str(def_id2).ends_with("noise_fns::generators::perlin::Perlin")
368+
}
369+
370+
fn is_rustybuzz_0_4_0(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> bool {
371+
let DeclKind::Import { import: i1, .. } = glob_decl.kind else { unreachable!() };
372+
let DeclKind::Import { import: i2, .. } = old_glob_decl.kind else { unreachable!() };
373+
let [seg1, seg2] = &i1.module_path[..] else { return false };
374+
if seg1.ident.name != kw::Super || seg2.ident.name.as_str() != "gsubgpos" {
375+
return false;
376+
}
377+
let [seg1] = &i2.module_path[..] else { return false };
378+
if seg1.ident.name != kw::Super {
379+
return false;
380+
}
381+
let Some(def_id1) = glob_decl.res().opt_def_id() else { return false };
382+
let Some(def_id2) = old_glob_decl.res().opt_def_id() else { return false };
383+
self.def_path_str(def_id1).ends_with("tables::gsubgpos::Class")
384+
&& self.def_path_str(def_id2).ends_with("ggg::Class")
385+
}
386+
355387
/// If `glob_decl` attempts to overwrite `old_glob_decl` in a module,
356388
/// decide which one to keep.
357-
fn select_glob_decl(
358-
&self,
359-
old_glob_decl: Decl<'ra>,
360-
glob_decl: Decl<'ra>,
361-
warn_ambiguity: bool,
362-
) -> Decl<'ra> {
389+
fn select_glob_decl(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> Decl<'ra> {
363390
assert!(glob_decl.is_glob_import());
364391
assert!(old_glob_decl.is_glob_import());
365392
assert_ne!(glob_decl, old_glob_decl);
@@ -368,9 +395,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
368395
// all these overwrites will be re-fetched by glob imports importing
369396
// from that module without generating new ambiguities.
370397
// - A glob decl is overwritten by a non-glob decl arriving later.
371-
// - A glob decl 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 decl in some way.
374398
// - A glob decl is overwritten by a glob decl re-fetching an
375399
// overwritten decl from other module (the recursive case).
376400
// Here we are detecting all such re-fetches and overwrite old decls
@@ -381,37 +405,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
381405
if deep_decl != glob_decl {
382406
// Some import layers have been removed, need to overwrite.
383407
assert_ne!(old_deep_decl, old_glob_decl);
384-
// FIXME: reenable the asserts when `warn_ambiguity` is removed (#149195).
385-
// assert_ne!(old_deep_decl, deep_decl);
386-
// assert!(old_deep_decl.is_glob_import());
408+
assert_ne!(old_deep_decl, deep_decl);
409+
assert!(old_deep_decl.is_glob_import());
387410
assert!(!deep_decl.is_glob_import());
388-
if old_glob_decl.ambiguity.get().is_some() && glob_decl.ambiguity.get().is_none() {
411+
if let Some((old_ambig, _)) = old_glob_decl.ambiguity.get()
412+
&& glob_decl.ambiguity.get().is_none()
413+
{
389414
// Do not lose glob ambiguities when re-fetching the glob.
390-
glob_decl.ambiguity.set_unchecked(old_glob_decl.ambiguity.get());
391-
}
392-
if glob_decl.is_ambiguity_recursive() {
393-
glob_decl.warn_ambiguity.set_unchecked(true);
415+
glob_decl.ambiguity.set_unchecked(Some((old_ambig, true)));
394416
}
395417
glob_decl
396418
} else if glob_decl.res() != old_glob_decl.res() {
397-
old_glob_decl.ambiguity.set_unchecked(Some(glob_decl));
398-
old_glob_decl.warn_ambiguity.set_unchecked(warn_ambiguity);
399-
if warn_ambiguity {
400-
old_glob_decl
401-
} else {
402-
// Need a fresh decl so other glob imports importing it could re-fetch it
403-
// and set their own `warn_ambiguity` to true.
404-
// FIXME: remove this when `warn_ambiguity` is removed (#149195).
405-
self.arenas.alloc_decl((*old_glob_decl).clone())
406-
}
419+
let warning = self.is_noise_0_7_0(old_glob_decl, glob_decl)
420+
|| self.is_rustybuzz_0_4_0(old_glob_decl, glob_decl);
421+
old_glob_decl.ambiguity.set_unchecked(Some((glob_decl, warning)));
422+
old_glob_decl
407423
} else if !old_glob_decl.vis().is_at_least(glob_decl.vis(), self.tcx) {
408424
// We are glob-importing the same item but with greater visibility.
409425
old_glob_decl.vis.set_unchecked(glob_decl.vis());
410426
old_glob_decl
411427
} else if glob_decl.is_ambiguity_recursive() && !old_glob_decl.is_ambiguity_recursive() {
412428
// Overwriting a non-ambiguous glob import with an ambiguous glob import.
413-
old_glob_decl.ambiguity.set_unchecked(Some(glob_decl));
414-
old_glob_decl.warn_ambiguity.set_unchecked(true);
429+
old_glob_decl.ambiguity.set_unchecked(Some((glob_decl, true)));
415430
old_glob_decl
416431
} else {
417432
old_glob_decl
@@ -426,7 +441,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
426441
orig_ident_span: Span,
427442
ns: Namespace,
428443
decl: Decl<'ra>,
429-
warn_ambiguity: bool,
430444
) -> Result<(), Decl<'ra>> {
431445
let module = decl.parent_module.unwrap();
432446
let res = decl.res();
@@ -438,52 +452,44 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
438452
module.underscore_disambiguator.update_unchecked(|d| d + 1);
439453
module.underscore_disambiguator.get()
440454
});
441-
self.update_local_resolution(
442-
module,
443-
key,
444-
orig_ident_span,
445-
warn_ambiguity,
446-
|this, resolution| {
447-
if let Some(old_decl) = resolution.best_decl() {
448-
assert_ne!(decl, old_decl);
449-
assert!(!decl.warn_ambiguity.get());
450-
if res == Res::Err && old_decl.res() != Res::Err {
451-
// Do not override real declarations with `Res::Err`s from error recovery.
452-
return Ok(());
455+
self.update_local_resolution(module, key, orig_ident_span, |this, resolution| {
456+
if let Some(old_decl) = resolution.best_decl() {
457+
assert_ne!(decl, old_decl);
458+
if res == Res::Err && old_decl.res() != Res::Err {
459+
// Do not override real declarations with `Res::Err`s from error recovery.
460+
return Ok(());
461+
}
462+
match (old_decl.is_glob_import(), decl.is_glob_import()) {
463+
(true, true) => {
464+
resolution.glob_decl = Some(this.select_glob_decl(old_decl, decl));
453465
}
454-
match (old_decl.is_glob_import(), decl.is_glob_import()) {
455-
(true, true) => {
466+
(old_glob @ true, false) | (old_glob @ false, true) => {
467+
let (glob_decl, non_glob_decl) =
468+
if old_glob { (old_decl, decl) } else { (decl, old_decl) };
469+
resolution.non_glob_decl = Some(non_glob_decl);
470+
if let Some(old_glob_decl) = resolution.glob_decl
471+
&& old_glob_decl != glob_decl
472+
{
456473
resolution.glob_decl =
457-
Some(this.select_glob_decl(old_decl, decl, warn_ambiguity));
458-
}
459-
(old_glob @ true, false) | (old_glob @ false, true) => {
460-
let (glob_decl, non_glob_decl) =
461-
if old_glob { (old_decl, decl) } else { (decl, old_decl) };
462-
resolution.non_glob_decl = Some(non_glob_decl);
463-
if let Some(old_glob_decl) = resolution.glob_decl
464-
&& old_glob_decl != glob_decl
465-
{
466-
resolution.glob_decl =
467-
Some(this.select_glob_decl(old_glob_decl, glob_decl, false));
468-
} else {
469-
resolution.glob_decl = Some(glob_decl);
470-
}
471-
}
472-
(false, false) => {
473-
return Err(old_decl);
474+
Some(this.select_glob_decl(old_glob_decl, glob_decl));
475+
} else {
476+
resolution.glob_decl = Some(glob_decl);
474477
}
475478
}
476-
} else {
477-
if decl.is_glob_import() {
478-
resolution.glob_decl = Some(decl);
479-
} else {
480-
resolution.non_glob_decl = Some(decl);
479+
(false, false) => {
480+
return Err(old_decl);
481481
}
482482
}
483+
} else {
484+
if decl.is_glob_import() {
485+
resolution.glob_decl = Some(decl);
486+
} else {
487+
resolution.non_glob_decl = Some(decl);
488+
}
489+
}
483490

484-
Ok(())
485-
},
486-
)
491+
Ok(())
492+
})
487493
}
488494

489495
// Use `f` to mutate the resolution of the name in the module.
@@ -493,15 +499,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
493499
module: Module<'ra>,
494500
key: BindingKey,
495501
orig_ident_span: Span,
496-
warn_ambiguity: bool,
497502
f: F,
498503
) -> T
499504
where
500505
F: FnOnce(&Resolver<'ra, 'tcx>, &mut NameResolution<'ra>) -> T,
501506
{
502507
// Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
503508
// during which the resolution might end up getting re-defined via a glob cycle.
504-
let (binding, t, warn_ambiguity) = {
509+
let (binding, t) = {
505510
let resolution = &mut *self
506511
.resolution_or_default(module, key, orig_ident_span)
507512
.borrow_mut_unchecked();
@@ -512,7 +517,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
512517
if let Some(binding) = resolution.binding()
513518
&& old_decl != Some(binding)
514519
{
515-
(binding, t, warn_ambiguity || old_decl.is_some())
520+
(binding, t)
516521
} else {
517522
return t;
518523
}
@@ -540,7 +545,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
540545
orig_ident_span,
541546
key.ns,
542547
import_decl,
543-
warn_ambiguity,
544548
);
545549
}
546550
}
@@ -560,25 +564,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
560564
self.per_ns(|this, ns| {
561565
let module = import.parent_scope.module;
562566
let ident = IdentKey::new(target);
563-
let _ = this.try_plant_decl_into_local_module(
564-
ident,
565-
target.span,
566-
ns,
567-
dummy_decl,
568-
false,
569-
);
567+
let _ = this.try_plant_decl_into_local_module(ident, target.span, ns, dummy_decl);
570568
// Don't remove underscores from `single_imports`, they were never added.
571569
if target.name != kw::Underscore {
572570
let key = BindingKey::new(ident, ns);
573-
this.update_local_resolution(
574-
module,
575-
key,
576-
target.span,
577-
false,
578-
|_, resolution| {
579-
resolution.single_imports.swap_remove(&import);
580-
},
581-
)
571+
this.update_local_resolution(module, key, target.span, |_, resolution| {
572+
resolution.single_imports.swap_remove(&import);
573+
})
582574
}
583575
});
584576
self.record_use(target, dummy_decl, Used::Other);
@@ -709,7 +701,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
709701
let Some(binding) = resolution.best_decl() else { continue };
710702

711703
if let DeclKind::Import { import, .. } = binding.kind
712-
&& let Some(amb_binding) = binding.ambiguity.get()
704+
&& let Some((amb_binding, _)) = binding.ambiguity.get()
713705
&& binding.res() != Res::Err
714706
&& exported_ambiguities.contains(&binding)
715707
{
@@ -968,7 +960,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
968960
parent,
969961
key,
970962
target.span,
971-
false,
972963
|_, resolution| {
973964
resolution.single_imports.swap_remove(&import);
974965
},
@@ -1579,16 +1570,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15791570
};
15801571
if self.is_accessible_from(binding.vis(), scope) {
15811572
let import_decl = self.new_import_decl(binding, import);
1582-
let warn_ambiguity = self
1583-
.resolution(import.parent_scope.module, key)
1584-
.and_then(|r| r.binding())
1585-
.is_some_and(|binding| binding.warn_ambiguity_recursive());
15861573
let _ = self.try_plant_decl_into_local_module(
15871574
key.ident,
15881575
orig_ident_span,
15891576
key.ns,
15901577
import_decl,
1591-
warn_ambiguity,
15921578
);
15931579
}
15941580
}

0 commit comments

Comments
 (0)