Skip to content

Commit 5a0a58e

Browse files
committed
Add ambiguous_panic_imports lint
This turns the ambiguous panic import error into a warning to avoid breaking large parts of the Rust crate ecosystem.
1 parent 3ddafc9 commit 5a0a58e

File tree

10 files changed

+164
-28
lines changed

10 files changed

+164
-28
lines changed

compiler/rustc_lint/src/early/diagnostics.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ pub fn decorate_builtin_lint(
257257

258258
lints::ExternCrateNotIdiomatic { span: suggestion_span, code }.decorate_lint(diag);
259259
}
260-
BuiltinLintDiag::AmbiguousGlobImports { diag: ambiguity } => {
261-
lints::AmbiguousGlobImports { ambiguity }.decorate_lint(diag);
260+
BuiltinLintDiag::AmbiguousImports { diag: ambiguity } => {
261+
lints::AmbiguousImports { ambiguity }.decorate_lint(diag);
262262
}
263263
BuiltinLintDiag::AmbiguousGlobReexports {
264264
name,

compiler/rustc_lint/src/lints.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2870,11 +2870,11 @@ pub(crate) struct ExternCrateNotIdiomatic {
28702870
}
28712871

28722872
// FIXME: make this translatable
2873-
pub(crate) struct AmbiguousGlobImports {
2873+
pub(crate) struct AmbiguousImports {
28742874
pub ambiguity: AmbiguityErrorDiag,
28752875
}
28762876

2877-
impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for AmbiguousGlobImports {
2877+
impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for AmbiguousImports {
28782878
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
28792879
diag.primary_message(self.ambiguity.msg.clone());
28802880
rustc_errors::report_ambiguity_error(diag, self.ambiguity);

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ declare_lint_pass! {
2121
AMBIGUOUS_ASSOCIATED_ITEMS,
2222
AMBIGUOUS_GLOB_IMPORTS,
2323
AMBIGUOUS_GLOB_REEXPORTS,
24+
AMBIGUOUS_PANIC_IMPORTS,
2425
ARITHMETIC_OVERFLOW,
2526
ASM_SUB_REGISTER,
2627
BAD_ASM_STYLE,
@@ -4488,6 +4489,43 @@ declare_lint! {
44884489
};
44894490
}
44904491

4492+
declare_lint! {
4493+
/// The `ambiguous_panic_imports` lint detects ambiguous core and std panic imports, but
4494+
/// previously didn't do that due to `#[macro_use]` prelude macro import.
4495+
///
4496+
/// ### Example
4497+
///
4498+
/// ```rust,compile_fail
4499+
/// #![deny(ambiguous_panic_imports)]
4500+
/// #![no_std]
4501+
///
4502+
/// extern crate std;
4503+
/// use std::prelude::v1::*;
4504+
///
4505+
/// fn xx() {
4506+
/// panic!(); // resolves to core::panic
4507+
/// }
4508+
/// ```
4509+
///
4510+
/// {{produces}}
4511+
///
4512+
/// ### Explanation
4513+
///
4514+
/// Future versions of Rust will no longer accept the ambiguous resolution.
4515+
///
4516+
/// This is a [future-incompatible] lint to transition this to a hard error in the future.
4517+
///
4518+
/// [future-incompatible]: ../index.md#future-incompatible-lints
4519+
pub AMBIGUOUS_PANIC_IMPORTS,
4520+
Warn,
4521+
"detects ambiguous core and std panic imports",
4522+
@future_incompatible = FutureIncompatibleInfo {
4523+
reason: FutureIncompatibilityReason::FutureReleaseError,
4524+
reference: "issue #147319 <https://github.com/rust-lang/rust/issues/147319>",
4525+
report_in_deps: true,
4526+
};
4527+
}
4528+
44914529
declare_lint! {
44924530
/// The `refining_impl_trait_reachable` lint detects `impl Trait` return
44934531
/// types in method signatures that are refined by a publically reachable

compiler/rustc_lint_defs/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ pub enum BuiltinLintDiag {
682682
vis_span: Span,
683683
ident_span: Span,
684684
},
685-
AmbiguousGlobImports {
685+
AmbiguousImports {
686686
diag: AmbiguityErrorDiag,
687687
},
688688
AmbiguousGlobReexports {

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc_middle::bug;
2121
use rustc_middle::ty::TyCtxt;
2222
use rustc_session::Session;
2323
use rustc_session::lint::builtin::{
24-
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS,
24+
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_PANIC_IMPORTS,
2525
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
2626
};
2727
use rustc_session::lint::{AmbiguityErrorDiag, BuiltinLintDiag};
@@ -42,9 +42,9 @@ use crate::errors::{
4242
use crate::imports::{Import, ImportKind};
4343
use crate::late::{DiagMetadata, PatternSource, Rib};
4444
use crate::{
45-
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, BindingKey, Finalize,
46-
ForwardGenericParamBanReason, HasGenericParams, LexicalScopeBinding, MacroRulesScope, Module,
47-
ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult,
45+
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, AmbiguityWarning, BindingError, BindingKey,
46+
Finalize, ForwardGenericParamBanReason, HasGenericParams, LexicalScopeBinding, MacroRulesScope,
47+
Module, ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult,
4848
PrivacyError, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used,
4949
VisResolutionError, errors as errs, path_names_to_string,
5050
};
@@ -144,15 +144,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
144144

145145
for ambiguity_error in &self.ambiguity_errors {
146146
let diag = self.ambiguity_diagnostics(ambiguity_error);
147-
if ambiguity_error.warning {
147+
if let Some(ambiguity_warning) = ambiguity_error.warning {
148148
let NameBindingKind::Import { import, .. } = ambiguity_error.b1.0.kind else {
149149
unreachable!()
150150
};
151+
152+
let lint = match ambiguity_warning {
153+
AmbiguityWarning::GlobImport => AMBIGUOUS_GLOB_IMPORTS,
154+
AmbiguityWarning::PanicImport => AMBIGUOUS_PANIC_IMPORTS,
155+
};
156+
151157
self.lint_buffer.buffer_lint(
152-
AMBIGUOUS_GLOB_IMPORTS,
158+
lint,
153159
import.root_id,
154160
ambiguity_error.ident.span,
155-
BuiltinLintDiag::AmbiguousGlobImports { diag },
161+
BuiltinLintDiag::AmbiguousImports { diag },
156162
);
157163
} else {
158164
let mut err = struct_span_code_err!(self.dcx(), diag.span, E0659, "{}", diag.msg);

compiler/rustc_resolve/src/ident.rs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ use crate::late::{
1717
};
1818
use crate::macros::{MacroRulesScope, sub_namespace_match};
1919
use crate::{
20-
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, CmResolver, Determinacy,
21-
Finalize, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot,
22-
NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError,
23-
Resolver, Scope, ScopeSet, Segment, Stage, Used, Weak, errors,
20+
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, AmbiguityWarning, BindingKey, CmResolver,
21+
Determinacy, Finalize, ImportKind, LexicalScopeBinding, Module, ModuleKind,
22+
ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res,
23+
ResolutionError, Resolver, Scope, ScopeSet, Segment, Stage, Used, Weak, errors,
2424
};
2525

2626
#[derive(Copy, Clone)]
@@ -705,13 +705,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
705705
// Skip ambiguity errors for extern flag bindings "overridden"
706706
// by extern item bindings.
707707
// FIXME: Remove with lang team approval.
708-
let issue_145575_hack = Some(binding)
709-
== extern_prelude_flag_binding
710-
&& extern_prelude_item_binding.is_some()
711-
&& extern_prelude_item_binding != Some(innermost_binding);
708+
let is_issue_145575_hack = || {
709+
Some(binding) == extern_prelude_flag_binding
710+
&& extern_prelude_item_binding.is_some()
711+
&& extern_prelude_item_binding != Some(innermost_binding)
712+
};
713+
712714
if let Some(kind) = ambiguity_error_kind
713-
&& !issue_145575_hack
715+
&& !is_issue_145575_hack()
714716
{
717+
// Turn ambiguity errors for core vs std panic into warnings.
718+
// FIXME: Remove with lang team approval.
719+
let is_issue_147319_hack = matches!(
720+
(binding.res(), innermost_binding.res()),
721+
(
722+
Res::Def(DefKind::Macro(_), def_id_core),
723+
Res::Def(DefKind::Macro(_), def_id_std)
724+
) if this.tcx.def_path_debug_str(def_id_core)
725+
== "core[234c]::macros::panic"
726+
&& this.tcx.def_path_debug_str(def_id_std)
727+
== "std[d474]::macros::panic"
728+
);
729+
730+
let warning = if is_issue_147319_hack {
731+
Some(AmbiguityWarning::PanicImport)
732+
} else {
733+
None
734+
};
735+
715736
let misc = |f: Flags| {
716737
if f.contains(Flags::MISC_SUGGEST_CRATE) {
717738
AmbiguityErrorMisc::SuggestCrate
@@ -728,7 +749,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
728749
ident: orig_ident,
729750
b1: innermost_binding,
730751
b2: binding,
731-
warning: false,
752+
warning,
732753
misc1: misc(innermost_flags),
733754
misc2: misc(flags),
734755
});
@@ -1072,7 +1093,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
10721093
ident,
10731094
b1: binding,
10741095
b2: shadowed_glob,
1075-
warning: false,
1096+
warning: None,
10761097
misc1: AmbiguityErrorMisc::None,
10771098
misc2: AmbiguityErrorMisc::None,
10781099
});

compiler/rustc_resolve/src/imports.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -945,8 +945,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
945945
ImportKind::Single { bindings, .. } => bindings[TypeNS].get().binding(),
946946
_ => None,
947947
};
948-
let ambiguity_errors_len =
949-
|errors: &Vec<AmbiguityError<'_>>| errors.iter().filter(|error| !error.warning).count();
948+
let ambiguity_errors_len = |errors: &Vec<AmbiguityError<'_>>| {
949+
errors.iter().filter(|error| error.warning.is_none()).count()
950+
};
950951
let prev_ambiguity_errors_len = ambiguity_errors_len(&self.ambiguity_errors);
951952
let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span);
952953

@@ -1161,7 +1162,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
11611162
});
11621163
let res = binding.res();
11631164
let has_ambiguity_error =
1164-
this.ambiguity_errors.iter().any(|error| !error.warning);
1165+
this.ambiguity_errors.iter().any(|error| error.warning.is_none());
11651166
if res == Res::Err || has_ambiguity_error {
11661167
this.dcx()
11671168
.span_delayed_bug(import.span, "some error happened for an import");

compiler/rustc_resolve/src/lib.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -907,14 +907,20 @@ enum AmbiguityErrorMisc {
907907
None,
908908
}
909909

910+
#[derive(Clone, Copy, PartialEq)]
911+
enum AmbiguityWarning {
912+
GlobImport,
913+
PanicImport,
914+
}
915+
910916
struct AmbiguityError<'ra> {
911917
kind: AmbiguityKind,
912918
ident: Ident,
913919
b1: NameBinding<'ra>,
914920
b2: NameBinding<'ra>,
915921
misc1: AmbiguityErrorMisc,
916922
misc2: AmbiguityErrorMisc,
917-
warning: bool,
923+
warning: Option<AmbiguityWarning>,
918924
}
919925

920926
impl<'ra> NameBindingData<'ra> {
@@ -2042,7 +2048,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
20422048
b2,
20432049
misc1: AmbiguityErrorMisc::None,
20442050
misc2: AmbiguityErrorMisc::None,
2045-
warning: warn_ambiguity,
2051+
warning: if warn_ambiguity { Some(AmbiguityWarning::GlobImport) } else { None },
20462052
};
20472053
if !self.matches_previous_ambiguity_error(&ambiguity_error) {
20482054
// avoid duplicated span information to be emit out
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![deny(ambiguous_panic_imports)]
2+
#![crate_type = "lib"]
3+
#![no_std]
4+
5+
extern crate std;
6+
use std::prelude::v1::*;
7+
8+
#[allow(unused)]
9+
fn xx() {
10+
panic!();
11+
//~^ ERROR `panic` 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!
13+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
error: `panic` is ambiguous
2+
--> $DIR/ambiguous-panic.rs:10:5
3+
|
4+
LL | panic!();
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 #147319 <https://github.com/rust-lang/rust/issues/147319>
9+
= note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
10+
note: `panic` could refer to the macro imported here
11+
--> $DIR/ambiguous-panic.rs:6:5
12+
|
13+
LL | use std::prelude::v1::*;
14+
| ^^^^^^^^^^^^^^^^^^^
15+
= help: consider adding an explicit import of `panic` to disambiguate
16+
= help: or use `crate::panic` to refer to this macro unambiguously
17+
note: `panic` could also refer to a macro from prelude
18+
--> $SRC_DIR/core/src/prelude/mod.rs:LL:COL
19+
note: the lint level is defined here
20+
--> $DIR/ambiguous-panic.rs:1:9
21+
|
22+
LL | #![deny(ambiguous_panic_imports)]
23+
| ^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error: aborting due to 1 previous error
26+
27+
Future incompatibility report: Future breakage diagnostic:
28+
error: `panic` is ambiguous
29+
--> $DIR/ambiguous-panic.rs:10:5
30+
|
31+
LL | panic!();
32+
| ^^^^^ ambiguous name
33+
|
34+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
35+
= note: for more information, see issue #147319 <https://github.com/rust-lang/rust/issues/147319>
36+
= note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
37+
note: `panic` could refer to the macro imported here
38+
--> $DIR/ambiguous-panic.rs:6:5
39+
|
40+
LL | use std::prelude::v1::*;
41+
| ^^^^^^^^^^^^^^^^^^^
42+
= help: consider adding an explicit import of `panic` to disambiguate
43+
= help: or use `crate::panic` to refer to this macro unambiguously
44+
note: `panic` could also refer to a macro from prelude
45+
--> $SRC_DIR/core/src/prelude/mod.rs:LL:COL
46+
note: the lint level is defined here
47+
--> $DIR/ambiguous-panic.rs:1:9
48+
|
49+
LL | #![deny(ambiguous_panic_imports)]
50+
| ^^^^^^^^^^^^^^^^^^^^^^^
51+

0 commit comments

Comments
 (0)