Skip to content

Commit 2dc6610

Browse files
committed
Auto merge of #113099 - bvanjoi:fix-112713-2, r=petrochenkov
fix(resolve): update the ambiguity glob binding as warning recursively Fixes #47525 Fixes #56593, but `issue-56593-2.rs` is not fixed to ensure backward compatibility. Fixes #98467 Fixes #105235 Fixes #112713 This PR had added a field called `warn_ambiguous` in `NameBinding` which is only for back compatibly reason and used for lint. More details: #112743 r? `@petrochenkov`
2 parents 5ed61a4 + 771c832 commit 2dc6610

Some content is hidden

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

66 files changed

+1535
-58
lines changed

compiler/rustc_errors/src/lib.rs

+16
Original file line numberDiff line numberDiff line change
@@ -1871,6 +1871,22 @@ pub fn add_elided_lifetime_in_path_suggestion(
18711871
});
18721872
}
18731873

1874+
pub fn report_ambiguity_error<'a, G: EmissionGuarantee>(
1875+
db: &mut DiagnosticBuilder<'a, G>,
1876+
ambiguity: rustc_lint_defs::AmbiguityErrorDiag,
1877+
) {
1878+
db.span_label(ambiguity.label_span, ambiguity.label_msg);
1879+
db.note(ambiguity.note_msg);
1880+
db.span_note(ambiguity.b1_span, ambiguity.b1_note_msg);
1881+
for help_msg in ambiguity.b1_help_msgs {
1882+
db.help(help_msg);
1883+
}
1884+
db.span_note(ambiguity.b2_span, ambiguity.b2_note_msg);
1885+
for help_msg in ambiguity.b2_help_msgs {
1886+
db.help(help_msg);
1887+
}
1888+
}
1889+
18741890
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
18751891
pub enum TerminalUrl {
18761892
No,

compiler/rustc_lint/src/context.rs

+3
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,9 @@ pub trait LintContext: Sized {
946946
Applicability::MachineApplicable,
947947
);
948948
}
949+
BuiltinLintDiagnostics::AmbiguousGlobImports { diag } => {
950+
rustc_errors::report_ambiguity_error(db, diag);
951+
}
949952
BuiltinLintDiagnostics::AmbiguousGlobReexports { name, namespace, first_reexport_span, duplicate_reexport_span } => {
950953
db.span_label(first_reexport_span, format!("the name `{name}` in the {namespace} namespace is first re-exported here"));
951954
db.span_label(duplicate_reexport_span, format!("but the name `{name}` in the {namespace} namespace is also re-exported here"));

compiler/rustc_lint_defs/src/builtin.rs

+44
Original file line numberDiff line numberDiff line change
@@ -3316,6 +3316,7 @@ declare_lint_pass! {
33163316
// tidy-alphabetical-start
33173317
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
33183318
AMBIGUOUS_ASSOCIATED_ITEMS,
3319+
AMBIGUOUS_GLOB_IMPORTS,
33193320
AMBIGUOUS_GLOB_REEXPORTS,
33203321
ARITHMETIC_OVERFLOW,
33213322
ASM_SUB_REGISTER,
@@ -4405,3 +4406,46 @@ declare_lint! {
44054406
Warn,
44064407
"unrecognized diagnostic attribute"
44074408
}
4409+
4410+
declare_lint! {
4411+
/// The `ambiguous_glob_imports` lint detects glob imports that should report ambiguity
4412+
/// errors, but previously didn't do that due to rustc bugs.
4413+
///
4414+
/// ### Example
4415+
///
4416+
/// ```rust,compile_fail
4417+
///
4418+
/// #![deny(ambiguous_glob_imports)]
4419+
/// pub fn foo() -> u32 {
4420+
/// use sub::*;
4421+
/// C
4422+
/// }
4423+
///
4424+
/// mod sub {
4425+
/// mod mod1 { pub const C: u32 = 1; }
4426+
/// mod mod2 { pub const C: u32 = 2; }
4427+
///
4428+
/// pub use mod1::*;
4429+
/// pub use mod2::*;
4430+
/// }
4431+
/// ```
4432+
///
4433+
/// {{produces}}
4434+
///
4435+
/// ### Explanation
4436+
///
4437+
/// Previous versions of Rust compile it successfully because it
4438+
/// had lost the ambiguity error when resolve `use sub::mod2::*`.
4439+
///
4440+
/// This is a [future-incompatible] lint to transition this to a
4441+
/// hard error in the future.
4442+
///
4443+
/// [future-incompatible]: ../index.md#future-incompatible-lints
4444+
pub AMBIGUOUS_GLOB_IMPORTS,
4445+
Warn,
4446+
"detects certain glob imports that require reporting an ambiguity error",
4447+
@future_incompatible = FutureIncompatibleInfo {
4448+
reason: FutureIncompatibilityReason::FutureReleaseError,
4449+
reference: "issue #114095 <https://github.com/rust-lang/rust/issues/114095>",
4450+
};
4451+
}

compiler/rustc_lint_defs/src/lib.rs

+18
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,21 @@ impl<HCX> ToStableHashKey<HCX> for LintId {
467467
}
468468
}
469469

470+
#[derive(Debug)]
471+
pub struct AmbiguityErrorDiag {
472+
pub msg: String,
473+
pub span: Span,
474+
pub label_span: Span,
475+
pub label_msg: String,
476+
pub note_msg: String,
477+
pub b1_span: Span,
478+
pub b1_note_msg: String,
479+
pub b1_help_msgs: Vec<String>,
480+
pub b2_span: Span,
481+
pub b2_note_msg: String,
482+
pub b2_help_msgs: Vec<String>,
483+
}
484+
470485
// This could be a closure, but then implementing derive trait
471486
// becomes hacky (and it gets allocated).
472487
#[derive(Debug)]
@@ -530,6 +545,9 @@ pub enum BuiltinLintDiagnostics {
530545
vis_span: Span,
531546
ident_span: Span,
532547
},
548+
AmbiguousGlobImports {
549+
diag: AmbiguityErrorDiag,
550+
},
533551
AmbiguousGlobReexports {
534552
/// The name for which collision(s) have occurred.
535553
name: String,

compiler/rustc_resolve/src/build_reduced_graph.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ impl<'a, Id: Into<DefId>> ToNameBinding<'a>
4141
arenas.alloc_name_binding(NameBindingData {
4242
kind: NameBindingKind::Module(self.0),
4343
ambiguity: None,
44+
warn_ambiguity: false,
4445
vis: self.1.to_def_id(),
4546
span: self.2,
4647
expansion: self.3,
@@ -53,6 +54,7 @@ impl<'a, Id: Into<DefId>> ToNameBinding<'a> for (Res, ty::Visibility<Id>, Span,
5354
arenas.alloc_name_binding(NameBindingData {
5455
kind: NameBindingKind::Res(self.0),
5556
ambiguity: None,
57+
warn_ambiguity: false,
5658
vis: self.1.to_def_id(),
5759
span: self.2,
5860
expansion: self.3,
@@ -69,7 +71,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
6971
{
7072
let binding = def.to_name_binding(self.arenas);
7173
let key = self.new_disambiguated_key(ident, ns);
72-
if let Err(old_binding) = self.try_define(parent, key, binding) {
74+
if let Err(old_binding) = self.try_define(parent, key, binding, false) {
7375
self.report_conflict(parent, ident, ns, old_binding, binding);
7476
}
7577
}

compiler/rustc_resolve/src/diagnostics.rs

+52-23
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ use rustc_ast::{self as ast, Crate, ItemKind, ModKind, NodeId, Path, CRATE_NODE_
55
use rustc_ast::{MetaItemKind, NestedMetaItem};
66
use rustc_ast_pretty::pprust;
77
use rustc_data_structures::fx::FxHashSet;
8-
use rustc_errors::{
9-
pluralize, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
10-
};
11-
use rustc_errors::{struct_span_err, SuggestionStyle};
8+
use rustc_errors::{pluralize, report_ambiguity_error, struct_span_err, SuggestionStyle};
9+
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
1210
use rustc_feature::BUILTIN_ATTRIBUTES;
1311
use rustc_hir::def::Namespace::{self, *};
1412
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS};
@@ -17,8 +15,9 @@ use rustc_hir::PrimTy;
1715
use rustc_middle::bug;
1816
use rustc_middle::ty::TyCtxt;
1917
use rustc_session::lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE;
18+
use rustc_session::lint::builtin::AMBIGUOUS_GLOB_IMPORTS;
2019
use rustc_session::lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS;
21-
use rustc_session::lint::BuiltinLintDiagnostics;
20+
use rustc_session::lint::{AmbiguityErrorDiag, BuiltinLintDiagnostics};
2221
use rustc_session::Session;
2322
use rustc_span::edit_distance::find_best_match_for_name;
2423
use rustc_span::edition::Edition;
@@ -135,7 +134,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
135134
}
136135

137136
for ambiguity_error in &self.ambiguity_errors {
138-
self.report_ambiguity_error(ambiguity_error);
137+
let diag = self.ambiguity_diagnostics(ambiguity_error);
138+
if ambiguity_error.warning {
139+
let NameBindingKind::Import { import, .. } = ambiguity_error.b1.0.kind else {
140+
unreachable!()
141+
};
142+
self.lint_buffer.buffer_lint_with_diagnostic(
143+
AMBIGUOUS_GLOB_IMPORTS,
144+
import.root_id,
145+
ambiguity_error.ident.span,
146+
diag.msg.to_string(),
147+
BuiltinLintDiagnostics::AmbiguousGlobImports { diag },
148+
);
149+
} else {
150+
let mut err = struct_span_err!(self.tcx.sess, diag.span, E0659, "{}", &diag.msg);
151+
report_ambiguity_error(&mut err, diag);
152+
err.emit();
153+
}
139154
}
140155

141156
let mut reported_spans = FxHashSet::default();
@@ -1540,20 +1555,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15401555
}
15411556
}
15421557

1543-
fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError<'_>) {
1544-
let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = *ambiguity_error;
1558+
fn ambiguity_diagnostics(&self, ambiguity_error: &AmbiguityError<'_>) -> AmbiguityErrorDiag {
1559+
let AmbiguityError { kind, ident, b1, b2, misc1, misc2, .. } = *ambiguity_error;
15451560
let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
15461561
// We have to print the span-less alternative first, otherwise formatting looks bad.
15471562
(b2, b1, misc2, misc1, true)
15481563
} else {
15491564
(b1, b2, misc1, misc2, false)
15501565
};
1551-
1552-
let mut err = struct_span_err!(self.tcx.sess, ident.span, E0659, "`{ident}` is ambiguous");
1553-
err.span_label(ident.span, "ambiguous name");
1554-
err.note(format!("ambiguous because of {}", kind.descr()));
1555-
1556-
let mut could_refer_to = |b: NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
1566+
let could_refer_to = |b: NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
15571567
let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
15581568
let note_msg = format!("`{ident}` could{also} refer to {what}");
15591569

@@ -1579,16 +1589,35 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15791589
AmbiguityErrorMisc::FromPrelude | AmbiguityErrorMisc::None => {}
15801590
}
15811591

1582-
err.span_note(b.span, note_msg);
1583-
for (i, help_msg) in help_msgs.iter().enumerate() {
1584-
let or = if i == 0 { "" } else { "or " };
1585-
err.help(format!("{}{}", or, help_msg));
1586-
}
1592+
(
1593+
b.span,
1594+
note_msg,
1595+
help_msgs
1596+
.iter()
1597+
.enumerate()
1598+
.map(|(i, help_msg)| {
1599+
let or = if i == 0 { "" } else { "or " };
1600+
format!("{}{}", or, help_msg)
1601+
})
1602+
.collect::<Vec<_>>(),
1603+
)
15871604
};
1588-
1589-
could_refer_to(b1, misc1, "");
1590-
could_refer_to(b2, misc2, " also");
1591-
err.emit();
1605+
let (b1_span, b1_note_msg, b1_help_msgs) = could_refer_to(b1, misc1, "");
1606+
let (b2_span, b2_note_msg, b2_help_msgs) = could_refer_to(b2, misc2, " also");
1607+
1608+
AmbiguityErrorDiag {
1609+
msg: format!("`{ident}` is ambiguous"),
1610+
span: ident.span,
1611+
label_span: ident.span,
1612+
label_msg: "ambiguous name".to_string(),
1613+
note_msg: format!("ambiguous because of {}", kind.descr()),
1614+
b1_span,
1615+
b1_note_msg,
1616+
b1_help_msgs,
1617+
b2_span,
1618+
b2_note_msg,
1619+
b2_help_msgs,
1620+
}
15921621
}
15931622

15941623
/// If the binding refers to a tuple struct constructor with fields,

compiler/rustc_resolve/src/ident.rs

+2
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
677677
ident: orig_ident,
678678
b1: innermost_binding,
679679
b2: binding,
680+
warning: false,
680681
misc1: misc(innermost_flags),
681682
misc2: misc(flags),
682683
});
@@ -905,6 +906,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
905906
ident,
906907
b1: binding,
907908
b2: shadowed_glob,
909+
warning: false,
908910
misc1: AmbiguityErrorMisc::None,
909911
misc2: AmbiguityErrorMisc::None,
910912
});

0 commit comments

Comments
 (0)