Skip to content

Commit 626c193

Browse files
committed
resolve: re-export ambiguity as warning
1 parent 832db2f commit 626c193

18 files changed

+207
-32
lines changed

compiler/rustc_errors/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1869,6 +1869,9 @@ pub fn report_ambiguity_error<'a, G: EmissionGuarantee>(
18691869
for help_msg in ambiguity.b1_help_msgs {
18701870
db.help(help_msg);
18711871
}
1872+
if ambiguity.extern_crate {
1873+
return;
1874+
}
18721875
db.span_note(ambiguity.b2_span, ambiguity.b2_note_msg);
18731876
for help_msg in ambiguity.b2_help_msgs {
18741877
db.help(help_msg);

compiler/rustc_lint_defs/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,9 @@ impl<HCX> ToStableHashKey<HCX> for LintId {
469469

470470
#[derive(Debug)]
471471
pub struct AmbiguityErrorDiag {
472+
/// Is this a ambiguity binding come from
473+
/// extern crate?
474+
pub extern_crate: bool,
472475
pub msg: String,
473476
pub span: Span,
474477
pub label_span: Span,

compiler/rustc_metadata/src/rmeta/decoder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1048,7 +1048,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
10481048
let res = Res::Def(self.def_kind(id), self.local_def_id(id));
10491049
let vis = self.get_visibility(id);
10501050

1051-
ModChild { ident, res, vis, reexport_chain: Default::default() }
1051+
ModChild { ident, res, vis, reexport_chain: Default::default(), ambiguity: false }
10521052
}
10531053

10541054
/// Iterates over all named children of the given module,

compiler/rustc_middle/src/metadata.rs

+2
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,6 @@ pub struct ModChild {
4343
/// Reexport chain linking this module child to its original reexported item.
4444
/// Empty if the module child is a proper item.
4545
pub reexport_chain: SmallVec<[Reexport; 2]>,
46+
/// Is this an ambiguous binding?
47+
pub ambiguity: bool,
4648
}

compiler/rustc_resolve/src/build_reduced_graph.rs

+49-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::def_collector::collect_definitions;
99
use crate::imports::{ImportData, ImportKind};
1010
use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
1111
use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
12-
use crate::{errors, BindingKey, MacroData, NameBindingData};
12+
use crate::{errors, AmbiguityKind, BindingKey, MacroData, NameBindingData};
1313
use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot};
1414
use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError};
1515
use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError};
@@ -62,6 +62,46 @@ impl<'a, Id: Into<DefId>> ToNameBinding<'a> for (Res, ty::Visibility<Id>, Span,
6262
}
6363
}
6464

65+
impl<'a, Id: Into<DefId>> ToNameBinding<'a>
66+
for (Module<'a>, ty::Visibility<Id>, Span, LocalExpnId, bool)
67+
{
68+
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> {
69+
let mut binding = NameBindingData {
70+
kind: NameBindingKind::Module(self.0),
71+
ambiguity: None,
72+
warn_ambiguity: false,
73+
vis: self.1.to_def_id(),
74+
span: self.2,
75+
expansion: self.3,
76+
};
77+
if self.4 {
78+
binding.ambiguity =
79+
Some((arenas.alloc_name_binding(binding.clone()), AmbiguityKind::ExternalCrate));
80+
binding.warn_ambiguity = true;
81+
}
82+
arenas.alloc_name_binding(binding)
83+
}
84+
}
85+
86+
impl<'a, Id: Into<DefId>> ToNameBinding<'a> for (Res, ty::Visibility<Id>, Span, LocalExpnId, bool) {
87+
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> {
88+
let mut binding = NameBindingData {
89+
kind: NameBindingKind::Res(self.0),
90+
ambiguity: None,
91+
warn_ambiguity: false,
92+
vis: self.1.to_def_id(),
93+
span: self.2,
94+
expansion: self.3,
95+
};
96+
if self.4 {
97+
binding.ambiguity =
98+
Some((arenas.alloc_name_binding(binding.clone()), AmbiguityKind::ExternalCrate));
99+
binding.warn_ambiguity = true;
100+
}
101+
arenas.alloc_name_binding(binding)
102+
}
103+
}
104+
65105
impl<'a, 'tcx> Resolver<'a, 'tcx> {
66106
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
67107
/// otherwise, reports an error.
@@ -71,7 +111,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
71111
{
72112
let binding = def.to_name_binding(self.arenas);
73113
let key = self.new_disambiguated_key(ident, ns);
74-
if let Err(old_binding) = self.try_define(parent, key, binding, false) {
114+
if let Err(old_binding) = self.try_define(parent, key, binding, binding.warn_ambiguity) {
75115
self.report_conflict(parent, ident, ns, old_binding, binding);
76116
}
77117
}
@@ -932,7 +972,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
932972
/// Builds the reduced graph for a single item in an external crate.
933973
fn build_reduced_graph_for_external_crate_res(&mut self, child: &ModChild) {
934974
let parent = self.parent_scope.module;
935-
let ModChild { ident, res, vis, ref reexport_chain } = *child;
975+
let ModChild { ident, res, vis, ref reexport_chain, ambiguity } = *child;
936976
let span = self.r.def_span(
937977
reexport_chain
938978
.first()
@@ -945,7 +985,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
945985
match res {
946986
Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, def_id) => {
947987
let module = self.r.expect_module(def_id);
948-
self.r.define(parent, ident, TypeNS, (module, vis, span, expansion));
988+
self.r.define(parent, ident, TypeNS, (module, vis, span, expansion, ambiguity));
949989
}
950990
Res::Def(
951991
DefKind::Struct
@@ -959,7 +999,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
959999
_,
9601000
)
9611001
| Res::PrimTy(..)
962-
| Res::ToolMod => self.r.define(parent, ident, TypeNS, (res, vis, span, expansion)),
1002+
| Res::ToolMod => {
1003+
self.r.define(parent, ident, TypeNS, (res, vis, span, expansion, ambiguity))
1004+
}
9631005
Res::Def(
9641006
DefKind::Fn
9651007
| DefKind::AssocFn
@@ -968,9 +1010,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
9681010
| DefKind::AssocConst
9691011
| DefKind::Ctor(..),
9701012
_,
971-
) => self.r.define(parent, ident, ValueNS, (res, vis, span, expansion)),
1013+
) => self.r.define(parent, ident, ValueNS, (res, vis, span, expansion, ambiguity)),
9721014
Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => {
973-
self.r.define(parent, ident, MacroNS, (res, vis, span, expansion))
1015+
self.r.define(parent, ident, MacroNS, (res, vis, span, expansion, ambiguity))
9741016
}
9751017
Res::Def(
9761018
DefKind::TyParam

compiler/rustc_resolve/src/diagnostics.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
136136
for ambiguity_error in &self.ambiguity_errors {
137137
let diag = self.ambiguity_diagnostics(ambiguity_error);
138138
if ambiguity_error.warning {
139-
let NameBindingKind::Import { import, .. } = ambiguity_error.b1.0.kind else {
140-
unreachable!()
141-
};
139+
let root_id =
140+
if let NameBindingKind::Import { import, .. } = ambiguity_error.b1.0.kind {
141+
import.root_id
142+
} else if ambiguity_error.kind == AmbiguityKind::ExternalCrate {
143+
krate.id
144+
} else {
145+
unreachable!()
146+
};
142147
self.lint_buffer.buffer_lint_with_diagnostic(
143148
AMBIGUOUS_GLOB_IMPORTS,
144-
import.root_id,
149+
root_id,
145150
ambiguity_error.ident.span,
146151
diag.msg.to_string(),
147152
BuiltinLintDiagnostics::AmbiguousGlobImports { diag },
@@ -1604,6 +1609,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
16041609
let (b2_span, b2_note_msg, b2_help_msgs) = could_refer_to(b2, misc2, " also");
16051610

16061611
AmbiguityErrorDiag {
1612+
extern_crate: kind == AmbiguityKind::ExternalCrate,
16071613
msg: format!("`{ident}` is ambiguous"),
16081614
span: ident.span,
16091615
label_span: ident.span,

compiler/rustc_resolve/src/imports.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -1407,11 +1407,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
14071407
};
14081408
if self.is_accessible_from(binding.vis, scope) {
14091409
let imported_binding = self.import(binding, import);
1410-
let warn_ambiguity = self
1411-
.resolution(import.parent_scope.module, key)
1412-
.borrow()
1413-
.binding()
1414-
.is_some_and(|binding| binding.is_warn_ambiguity());
1410+
let warn_ambiguity = imported_binding.is_warn_ambiguity();
14151411
let _ = self.try_define(
14161412
import.parent_scope.module,
14171413
key,
@@ -1436,16 +1432,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
14361432

14371433
module.for_each_child(self, |this, ident, _, binding| {
14381434
let res = binding.res().expect_non_local();
1439-
let error_ambiguity = binding.is_ambiguity() && !binding.warn_ambiguity;
1440-
if res != def::Res::Err && !error_ambiguity {
1435+
if res != def::Res::Err {
14411436
let mut reexport_chain = SmallVec::new();
14421437
let mut next_binding = binding;
14431438
while let NameBindingKind::Import { binding, import, .. } = next_binding.kind {
14441439
reexport_chain.push(import.simplify(this));
14451440
next_binding = binding;
14461441
}
1447-
1448-
children.push(ModChild { ident, res, vis: binding.vis, reexport_chain });
1442+
let ambiguity = binding.is_ambiguity();
1443+
children.push(ModChild {
1444+
ident,
1445+
res,
1446+
vis: binding.vis,
1447+
reexport_chain,
1448+
ambiguity,
1449+
});
14491450
}
14501451
});
14511452

compiler/rustc_resolve/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,7 @@ enum AmbiguityKind {
729729
GlobVsGlob,
730730
GlobVsExpanded,
731731
MoreExpandedVsOuter,
732+
ExternalCrate,
732733
}
733734

734735
impl AmbiguityKind {
@@ -749,6 +750,7 @@ impl AmbiguityKind {
749750
AmbiguityKind::MoreExpandedVsOuter => {
750751
"a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution"
751752
}
753+
AmbiguityKind::ExternalCrate => "it has some error in extern crate",
752754
}
753755
}
754756
}

tests/ui/imports/ambiguous-2.rs

+2
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ extern crate ambiguous_1;
66

77
fn main() {
88
ambiguous_1::id();
9+
//~^ WARNING `id` is ambiguous
10+
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
911
}

tests/ui/imports/ambiguous-2.stderr

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
warning: `id` is ambiguous
2+
--> $DIR/ambiguous-2.rs:8:18
3+
|
4+
LL | ambiguous_1::id();
5+
| ^^ ambiguous name
6+
|
7+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8+
= note: for more information, see issue #114095 <https://github.com/rust-lang/rust/issues/114095>
9+
= note: ambiguous because of it has some error in extern crate
10+
note: `id` could refer to the function defined here
11+
--> $DIR/auxiliary/../ambiguous-1.rs:24:9
12+
|
13+
LL | pub use openssl::*;
14+
| ^^^^^^^
15+
= note: `#[warn(ambiguous_glob_imports)]` on by default
16+
17+
warning: 1 warning emitted
18+

tests/ui/imports/ambiguous-4.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ extern crate ambiguous_4_extern;
55

66
fn main() {
77
ambiguous_4_extern::id();
8-
// `warning_ambiguous` had been lost at metadata.
8+
//~^ WARNING `id` is ambiguous
9+
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
910
}

tests/ui/imports/ambiguous-4.stderr

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
warning: `id` is ambiguous
2+
--> $DIR/ambiguous-4.rs:7:25
3+
|
4+
LL | ambiguous_4_extern::id();
5+
| ^^ ambiguous name
6+
|
7+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8+
= note: for more information, see issue #114095 <https://github.com/rust-lang/rust/issues/114095>
9+
= note: ambiguous because of it has some error in extern crate
10+
note: `id` could refer to the function defined here
11+
--> $DIR/auxiliary/../ambiguous-4-extern.rs:10:9
12+
|
13+
LL | pub use evp::*;
14+
| ^^^
15+
= note: `#[warn(ambiguous_glob_imports)]` on by default
16+
17+
warning: 1 warning emitted
18+

tests/ui/imports/extern-with-ambiguous-2.rs

+2
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@ mod s {
1212
use s::*;
1313
use extern_with_ambiguous_2_extern::*;
1414
use error::*;
15+
//~^ WARNING `error` is ambiguous
16+
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
1517

1618
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
warning: `error` is ambiguous
2+
--> $DIR/extern-with-ambiguous-2.rs:14:5
3+
|
4+
LL | use error::*;
5+
| ^^^^^ ambiguous name
6+
|
7+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8+
= note: for more information, see issue #114095 <https://github.com/rust-lang/rust/issues/114095>
9+
= note: ambiguous because of multiple glob imports of a name in the same module
10+
note: `error` could refer to the module imported here
11+
--> $DIR/extern-with-ambiguous-2.rs:12:5
12+
|
13+
LL | use s::*;
14+
| ^^^^
15+
= help: consider adding an explicit import of `error` to disambiguate
16+
note: `error` could also refer to the module imported here
17+
--> $DIR/extern-with-ambiguous-2.rs:13:5
18+
|
19+
LL | use extern_with_ambiguous_2_extern::*;
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21+
= help: consider adding an explicit import of `error` to disambiguate
22+
= note: `#[warn(ambiguous_glob_imports)]` on by default
23+
24+
warning: 1 warning emitted
25+

tests/ui/imports/extern-with-ambiguous-3.rs

+2
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,7 @@ mod s {
1313
use s::*;
1414
use extern_with_ambiguous_3_extern::*;
1515
use error::*;
16+
//~^ WARNING `error` is ambiguous
17+
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
1618

1719
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
warning: `error` is ambiguous
2+
--> $DIR/extern-with-ambiguous-3.rs:15:5
3+
|
4+
LL | use error::*;
5+
| ^^^^^ ambiguous name
6+
|
7+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8+
= note: for more information, see issue #114095 <https://github.com/rust-lang/rust/issues/114095>
9+
= note: ambiguous because of multiple glob imports of a name in the same module
10+
note: `error` could refer to the module imported here
11+
--> $DIR/extern-with-ambiguous-3.rs:13:5
12+
|
13+
LL | use s::*;
14+
| ^^^^
15+
= help: consider adding an explicit import of `error` to disambiguate
16+
note: `error` could also refer to the module imported here
17+
--> $DIR/extern-with-ambiguous-3.rs:14:5
18+
|
19+
LL | use extern_with_ambiguous_3_extern::*;
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21+
= help: consider adding an explicit import of `error` to disambiguate
22+
= note: `#[warn(ambiguous_glob_imports)]` on by default
23+
24+
warning: 1 warning emitted
25+
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
// check-pass
12
// aux-build:glob-conflict.rs
23

34
extern crate glob_conflict;
45

56
fn main() {
6-
glob_conflict::f(); //~ ERROR cannot find function `f` in crate `glob_conflict`
7-
glob_conflict::glob::f(); //~ ERROR cannot find function `f` in module `glob_conflict::glob`
7+
glob_conflict::f();
8+
//~^ WARNING `f` is ambiguous
9+
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
10+
glob_conflict::glob::f();
11+
//~^ WARNING `f` is ambiguous
12+
//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
813
}

0 commit comments

Comments
 (0)