Skip to content

Commit 4907eac

Browse files
committed
Auto merge of #154149 - petrochenkov:globvisglob, r=<try>
resolve: Extend `ambiguous_import_visibilities` deprecation lint to glob-vs-glob ambiguities
2 parents bfc05d6 + 8c30e81 commit 4907eac

17 files changed

+292
-139
lines changed

‎compiler/rustc_lint_defs/src/builtin.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4745,7 +4745,7 @@ declare_lint! {
47454745
///
47464746
/// [future-incompatible]: ../index.md#future-incompatible-lints
47474747
pub AMBIGUOUS_IMPORT_VISIBILITIES,
4748-
Warn,
4748+
Deny,
47494749
"detects certain glob imports that require reporting an ambiguity error",
47504750
@future_incompatible = FutureIncompatibleInfo {
47514751
reason: fcw!(FutureReleaseError #149145),

‎compiler/rustc_middle/src/middle/privacy.rs‎

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::hash::Hash;
77
use rustc_data_structures::fx::{FxIndexMap, IndexEntry};
88
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
99
use rustc_hir::def::DefKind;
10+
use rustc_hir::{ItemKind, Node, UseKind};
1011
use rustc_macros::HashStable;
1112
use rustc_span::def_id::{CRATE_DEF_ID, LocalDefId};
1213

@@ -184,13 +185,20 @@ impl EffectiveVisibilities {
184185
if !is_impl && tcx.trait_impl_of_assoc(def_id.to_def_id()).is_none() {
185186
let nominal_vis = tcx.visibility(def_id);
186187
if !nominal_vis.is_at_least(ev.reachable, tcx) {
187-
span_bug!(
188-
span,
189-
"{:?}: reachable {:?} > nominal {:?}",
190-
def_id,
191-
ev.reachable,
192-
nominal_vis,
193-
);
188+
if let Node::Item(item) = tcx.hir_node_by_def_id(def_id)
189+
&& let ItemKind::Use(_, UseKind::Glob) = item.kind
190+
{
191+
// Glob import visibilities can be increasee by other
192+
// more public glob imports in cases of ambiguity.
193+
} else {
194+
span_bug!(
195+
span,
196+
"{:?}: reachable {:?} > nominal {:?}",
197+
def_id,
198+
ev.reachable,
199+
nominal_vis,
200+
);
201+
}
194202
}
195203
}
196204
}

‎compiler/rustc_resolve/src/build_reduced_graph.rs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
9595
ambiguity: CmCell::new(ambiguity),
9696
// External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment.
9797
warn_ambiguity: CmCell::new(true),
98-
vis: CmCell::new(vis),
98+
initial_vis: vis,
99+
ambiguity_vis_max: CmCell::new(None),
100+
ambiguity_vis_min: CmCell::new(None),
99101
span,
100102
expansion,
101103
parent_module: Some(parent),

‎compiler/rustc_resolve/src/effective_visibilities.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
182182
parent_id.level(),
183183
tcx,
184184
);
185+
if let Some(max_vis_decl) = decl.ambiguity_vis_max.get() {
186+
// Avoid the most visible import in an ambiguous glob set being reported as unused.
187+
self.update_import(max_vis_decl, parent_id);
188+
}
185189
}
186190

187191
fn update_def(

‎compiler/rustc_resolve/src/ident.rs‎

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use Namespace::*;
55
use rustc_ast::{self as ast, NodeId};
66
use rustc_errors::ErrorGuaranteed;
77
use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS};
8+
use rustc_hir::def_id::DefId;
89
use rustc_middle::ty::Visibility;
910
use rustc_middle::{bug, span_bug};
1011
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
@@ -492,6 +493,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
492493
}
493494
Some(Finalize { import_vis, .. }) => import_vis,
494495
};
496+
this.get_mut().maybe_push_glob_vs_glob_vis_ambiguity(
497+
ident,
498+
orig_ident_span,
499+
decl,
500+
import_vis,
501+
);
495502

496503
if let Some(&(innermost_decl, _)) = innermost_results.first() {
497504
// Found another solution, if the first one was "weak", report an error.
@@ -774,6 +781,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
774781
ret.map_err(ControlFlow::Continue)
775782
}
776783

784+
fn maybe_push_glob_vs_glob_vis_ambiguity(
785+
&mut self,
786+
ident: IdentKey,
787+
orig_ident_span: Span,
788+
decl: Decl<'ra>,
789+
import_vis: Option<Visibility>,
790+
) {
791+
let Some(import_vis) = import_vis else { return };
792+
let min = |vis: Visibility<DefId>| vis.min(import_vis.to_def_id(), self.tcx).expect_local();
793+
let (min1, min2) = (min(decl.vis()), min(decl.min_vis()));
794+
if min1 != min2 {
795+
self.ambiguity_errors.push(AmbiguityError {
796+
kind: AmbiguityKind::GlobVsGlob,
797+
ambig_vis: Some((min1, min2)),
798+
ident: ident.orig(orig_ident_span),
799+
b1: decl.ambiguity_vis_max.get().unwrap_or(decl),
800+
b2: decl.ambiguity_vis_min.get().unwrap_or(decl),
801+
scope1: Scope::ModuleGlobs(decl.parent_module.unwrap(), None),
802+
scope2: Scope::ModuleGlobs(decl.parent_module.unwrap(), None),
803+
warning: Some(AmbiguityWarning::GlobImport),
804+
});
805+
}
806+
}
807+
777808
fn maybe_push_ambiguity(
778809
&mut self,
779810
ident: IdentKey,
@@ -894,16 +925,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
894925
None
895926
};
896927

897-
self.ambiguity_errors.push(AmbiguityError {
898-
kind,
899-
ambig_vis,
900-
ident: ident.orig(orig_ident_span),
901-
b1: innermost_decl,
902-
b2: decl,
903-
scope1: innermost_scope,
904-
scope2: scope,
905-
warning,
906-
});
928+
if ambig_vis.is_none() {
929+
self.ambiguity_errors.push(AmbiguityError {
930+
kind,
931+
ambig_vis,
932+
ident: ident.orig(orig_ident_span),
933+
b1: innermost_decl,
934+
b2: decl,
935+
scope1: innermost_scope,
936+
scope2: scope,
937+
warning,
938+
});
939+
}
907940
return true;
908941
}
909942
}

‎compiler/rustc_resolve/src/imports.rs‎

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
346346
ambiguity: CmCell::new(None),
347347
warn_ambiguity: CmCell::new(false),
348348
span: import.span,
349-
vis: CmCell::new(vis),
349+
initial_vis: vis,
350+
ambiguity_vis_max: CmCell::new(None),
351+
ambiguity_vis_min: CmCell::new(None),
350352
expansion: import.parent_scope.expansion,
351353
parent_module: Some(import.parent_scope.module),
352354
})
@@ -371,8 +373,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
371373
// - A glob decl is overwritten by its clone after setting ambiguity in it.
372374
// FIXME: avoid this by removing `warn_ambiguity`, or by triggering glob re-fetch
373375
// with the same decl in some way.
374-
// - A glob decl is overwritten by a glob decl with larger visibility.
375-
// FIXME: avoid this by updating this visibility in place.
376376
// - A glob decl is overwritten by a glob decl re-fetching an
377377
// overwritten decl from other module (the recursive case).
378378
// Here we are detecting all such re-fetches and overwrite old decls
@@ -386,8 +386,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
386386
// FIXME: reenable the asserts when `warn_ambiguity` is removed (#149195).
387387
// assert_ne!(old_deep_decl, deep_decl);
388388
// assert!(old_deep_decl.is_glob_import());
389-
// FIXME: reenable the assert when visibility is updated in place.
390-
// assert!(!deep_decl.is_glob_import());
389+
assert!(!deep_decl.is_glob_import());
391390
if old_glob_decl.ambiguity.get().is_some() && glob_decl.ambiguity.get().is_none() {
392391
// Do not lose glob ambiguities when re-fetching the glob.
393392
glob_decl.ambiguity.set_unchecked(old_glob_decl.ambiguity.get());
@@ -407,11 +406,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
407406
// FIXME: remove this when `warn_ambiguity` is removed (#149195).
408407
self.arenas.alloc_decl((*old_glob_decl).clone())
409408
}
410-
} else if !old_glob_decl.vis().is_at_least(glob_decl.vis(), self.tcx) {
411-
// We are glob-importing the same item but with greater visibility.
412-
// FIXME: Update visibility in place, but without regressions
413-
// (#152004, #151124, #152347).
414-
glob_decl
409+
} else if let old_vis = old_glob_decl.vis()
410+
&& let vis = glob_decl.vis()
411+
&& old_vis != vis
412+
{
413+
// We are glob-importing the same item but with a different visibility.
414+
if vis.is_at_least(old_vis, self.tcx) {
415+
old_glob_decl.ambiguity_vis_max.set_unchecked(Some(glob_decl));
416+
} else if let old_min_vis = old_glob_decl.min_vis()
417+
&& old_min_vis != vis
418+
&& old_min_vis.is_at_least(vis, self.tcx)
419+
{
420+
old_glob_decl.ambiguity_vis_min.set_unchecked(Some(glob_decl));
421+
}
422+
old_glob_decl
415423
} else if glob_decl.is_ambiguity_recursive() && !old_glob_decl.is_ambiguity_recursive() {
416424
// Overwriting a non-ambiguous glob import with an ambiguous glob import.
417425
old_glob_decl.ambiguity.set_unchecked(Some(glob_decl));
@@ -510,11 +518,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
510518
.resolution_or_default(module, key, orig_ident_span)
511519
.borrow_mut_unchecked();
512520
let old_decl = resolution.binding();
521+
let old_vis = old_decl.map(|d| d.vis());
513522

514523
let t = f(self, resolution);
515524

516525
if let Some(binding) = resolution.binding()
517-
&& old_decl != Some(binding)
526+
&& (old_decl != Some(binding) || old_vis != Some(binding.vis()))
518527
{
519528
(binding, t, warn_ambiguity || old_decl.is_some())
520529
} else {

‎compiler/rustc_resolve/src/lib.rs‎

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,13 @@ struct DeclData<'ra> {
850850
warn_ambiguity: CmCell<bool>,
851851
expansion: LocalExpnId,
852852
span: Span,
853-
vis: CmCell<Visibility<DefId>>,
853+
initial_vis: Visibility<DefId>,
854+
/// If the declaration refers to an ambiguous glob set, then this is the most visible binding
855+
/// from the set, if its visibility is different from `initial_vis`.
856+
ambiguity_vis_max: CmCell<Option<Decl<'ra>>>,
857+
/// If the declaration refers to an ambiguous glob set, then this is the least visible binding
858+
/// from the set, if its visibility is different from `initial_vis`.
859+
ambiguity_vis_min: CmCell<Option<Decl<'ra>>>,
854860
parent_module: Option<Module<'ra>>,
855861
}
856862

@@ -970,7 +976,13 @@ struct AmbiguityError<'ra> {
970976

971977
impl<'ra> DeclData<'ra> {
972978
fn vis(&self) -> Visibility<DefId> {
973-
self.vis.get()
979+
// Select the maximum visibility if there are multiple ambiguous glob imports.
980+
self.ambiguity_vis_max.get().map(|d| d.vis()).unwrap_or_else(|| self.initial_vis)
981+
}
982+
983+
fn min_vis(&self) -> Visibility<DefId> {
984+
// Select the minimum visibility if there are multiple ambiguous glob imports.
985+
self.ambiguity_vis_min.get().map(|d| d.vis()).unwrap_or_else(|| self.initial_vis)
974986
}
975987

976988
fn res(&self) -> Res {
@@ -1415,7 +1427,9 @@ impl<'ra> ResolverArenas<'ra> {
14151427
kind: DeclKind::Def(res),
14161428
ambiguity: CmCell::new(None),
14171429
warn_ambiguity: CmCell::new(false),
1418-
vis: CmCell::new(vis),
1430+
initial_vis: vis,
1431+
ambiguity_vis_max: CmCell::new(None),
1432+
ambiguity_vis_min: CmCell::new(None),
14191433
span,
14201434
expansion,
14211435
parent_module,
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
mod m {
2+
pub struct S {}
3+
}
4+
5+
mod min_vis_first {
6+
use crate::m::*;
7+
pub(crate) use crate::m::*;
8+
pub use crate::m::*;
9+
10+
pub use self::S as S1;
11+
//~^ ERROR ambiguous import visibility
12+
//~| WARN this was previously accepted
13+
pub(crate) use self::S as S2;
14+
//~^ ERROR ambiguous import visibility
15+
//~| WARN this was previously accepted
16+
use self::S as S3; // OK
17+
}
18+
19+
mod mid_vis_first {
20+
pub(crate) use crate::m::*;
21+
use crate::m::*;
22+
pub use crate::m::*;
23+
24+
pub use self::S as S1;
25+
//~^ ERROR ambiguous import visibility
26+
//~| WARN this was previously accepted
27+
pub(crate) use self::S as S2;
28+
//~^ ERROR ambiguous import visibility
29+
//~| WARN this was previously accepted
30+
use self::S as S3; // OK
31+
}
32+
33+
mod max_vis_first {
34+
pub use crate::m::*;
35+
use crate::m::*;
36+
pub(crate) use crate::m::*;
37+
38+
pub use self::S as S1;
39+
//~^ ERROR ambiguous import visibility
40+
//~| WARN this was previously accepted
41+
pub(crate) use self::S as S2;
42+
//~^ ERROR ambiguous import visibility
43+
//~| WARN this was previously accepted
44+
use self::S as S3; // OK
45+
}
46+
47+
fn main() {}

0 commit comments

Comments
 (0)