Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7590745
Explicitly export core and std macros
Voultapher Apr 7, 2025
d92b120
Apply review comments
Voultapher Apr 8, 2025
c88a7f1
Fix formatting tidy issues
Voultapher Apr 8, 2025
a58596f
Special case vec macro
Voultapher Apr 8, 2025
2b7fd0e
Explicitly import format_args_nl
Voultapher Apr 9, 2025
b9eb687
Exclude panic and env namespaces from prelude
Voultapher Apr 9, 2025
b404cb7
Explicitly use std panic over core panic
Voultapher Apr 11, 2025
792ec20
Remove #[macro_use] std/core from tests
Voultapher Apr 11, 2025
bb7aeb5
Update prelude macros
Voultapher Jun 25, 2025
cb27a81
Fix feature-gate-format_args_nl UI test
Voultapher Jun 25, 2025
67e0774
Apply review comments
Voultapher Jun 25, 2025
4b29fe2
Fix macro import in alloctests
Voultapher Jul 7, 2025
0f9a11e
Fix rustdoc macro inlining issues
Voultapher Jul 10, 2025
7ecf646
Adapt pretty tests expected outputs
Voultapher Jul 10, 2025
d8e5f4e
Silence unproblematic warning
Voultapher Aug 14, 2025
684be2f
Bless UI tests
Voultapher Aug 14, 2025
df8f47a
Fix alloctests again
Voultapher Aug 15, 2025
5d3b4e1
Appease clippy
Voultapher Aug 15, 2025
95f9e79
Export new hash_map macro
Voultapher Aug 15, 2025
da3dd66
Fix deriving-all-codegen UI test
Voultapher Aug 16, 2025
96fe81c
Bless pretty test output changes
Voultapher Aug 17, 2025
c74e610
Adjust println-type test to include prelude items
Voultapher Sep 18, 2025
e256c7b
Add ambiguous_panic_imports lint
Voultapher Oct 4, 2025
e5c2838
Improve is_issue_147319_hack check
Voultapher Oct 17, 2025
21942cd
Fix rebase issue
Voultapher Oct 17, 2025
6d509ce
Accept inconsistent macro resolution for workaround
Voultapher Oct 23, 2025
2fcaddb
Change ambiguous_panic_imports to report_in_deps false
Voultapher Nov 9, 2025
448e516
Add test cases
yaahc Dec 1, 2025
d2f5ccd
Trigger lint more narrowly and tiebreak to prelude
yaahc Dec 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub fn inject(

let item = cx.item(
span,
thin_vec![cx.attr_word(sym::macro_use, span)],
ast::AttrVec::new(),
ast::ItemKind::ExternCrate(None, Ident::new(name, ident_span)),
);

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_lint/src/early/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ pub fn decorate_builtin_lint(

lints::ExternCrateNotIdiomatic { span: suggestion_span, code }.decorate_lint(diag);
}
BuiltinLintDiag::AmbiguousGlobImports { diag: ambiguity } => {
lints::AmbiguousGlobImports { ambiguity }.decorate_lint(diag);
BuiltinLintDiag::AmbiguousImports { diag: ambiguity } => {
lints::AmbiguousImports { ambiguity }.decorate_lint(diag);
}
BuiltinLintDiag::AmbiguousGlobReexports {
name,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2870,11 +2870,11 @@ pub(crate) struct ExternCrateNotIdiomatic {
}

// FIXME: make this translatable
pub(crate) struct AmbiguousGlobImports {
pub(crate) struct AmbiguousImports {
pub ambiguity: AmbiguityErrorDiag,
}

impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for AmbiguousGlobImports {
impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for AmbiguousImports {
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
diag.primary_message(self.ambiguity.msg.clone());
rustc_errors::report_ambiguity_error(diag, self.ambiguity);
Expand Down
38 changes: 38 additions & 0 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ declare_lint_pass! {
AMBIGUOUS_ASSOCIATED_ITEMS,
AMBIGUOUS_GLOB_IMPORTS,
AMBIGUOUS_GLOB_REEXPORTS,
AMBIGUOUS_PANIC_IMPORTS,
ARITHMETIC_OVERFLOW,
ASM_SUB_REGISTER,
BAD_ASM_STYLE,
Expand Down Expand Up @@ -4488,6 +4489,43 @@ declare_lint! {
};
}

declare_lint! {
/// The `ambiguous_panic_imports` lint detects ambiguous core and std panic imports, but
/// previously didn't do that due to `#[macro_use]` prelude macro import.
///
/// ### Example
///
/// ```rust,compile_fail
/// #![deny(ambiguous_panic_imports)]
/// #![no_std]
///
/// extern crate std;
/// use std::prelude::v1::*;
///
/// fn xx() {
/// panic!(); // resolves to core::panic
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Future versions of Rust will no longer accept the ambiguous resolution.
///
/// This is a [future-incompatible] lint to transition this to a hard error in the future.
///
/// [future-incompatible]: ../index.md#future-incompatible-lints
pub AMBIGUOUS_PANIC_IMPORTS,
Warn,
"detects ambiguous core and std panic imports",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #147319 <https://github.com/rust-lang/rust/issues/147319>",
report_in_deps: false,
};
}

declare_lint! {
/// The `refining_impl_trait_reachable` lint detects `impl Trait` return
/// types in method signatures that are refined by a publically reachable
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint_defs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ pub enum BuiltinLintDiag {
vis_span: Span,
ident_span: Span,
},
AmbiguousGlobImports {
AmbiguousImports {
diag: AmbiguityErrorDiag,
},
AmbiguousGlobReexports {
Expand Down
20 changes: 13 additions & 7 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_session::lint::builtin::{
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS,
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_PANIC_IMPORTS,
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
};
use rustc_session::lint::{AmbiguityErrorDiag, BuiltinLintDiag};
Expand All @@ -42,9 +42,9 @@ use crate::errors::{
use crate::imports::{Import, ImportKind};
use crate::late::{DiagMetadata, PatternSource, Rib};
use crate::{
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, BindingKey, Finalize,
ForwardGenericParamBanReason, HasGenericParams, LexicalScopeBinding, MacroRulesScope, Module,
ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult,
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, AmbiguityWarning, BindingError, BindingKey,
Finalize, ForwardGenericParamBanReason, HasGenericParams, LexicalScopeBinding, MacroRulesScope,
Module, ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult,
PrivacyError, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used,
VisResolutionError, errors as errs, path_names_to_string,
};
Expand Down Expand Up @@ -144,15 +144,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {

for ambiguity_error in &self.ambiguity_errors {
let diag = self.ambiguity_diagnostics(ambiguity_error);
if ambiguity_error.warning {
if let Some(ambiguity_warning) = ambiguity_error.warning {
let NameBindingKind::Import { import, .. } = ambiguity_error.b1.0.kind else {
unreachable!()
};

let lint = match ambiguity_warning {
AmbiguityWarning::GlobImport => AMBIGUOUS_GLOB_IMPORTS,
AmbiguityWarning::PanicImport => AMBIGUOUS_PANIC_IMPORTS,
};

self.lint_buffer.buffer_lint(
AMBIGUOUS_GLOB_IMPORTS,
lint,
import.root_id,
ambiguity_error.ident.span,
BuiltinLintDiag::AmbiguousGlobImports { diag },
BuiltinLintDiag::AmbiguousImports { diag },
);
} else {
let mut err = struct_span_code_err!(self.dcx(), diag.span, E0659, "{}", diag.msg);
Expand Down
86 changes: 65 additions & 21 deletions compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRe
use rustc_middle::{bug, span_bug};
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
use rustc_session::parse::feature_err;
use rustc_span::edition::Edition;
use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
use rustc_span::{Ident, Span, kw, sym};
use tracing::{debug, instrument};
Expand All @@ -17,10 +18,10 @@ use crate::late::{
};
use crate::macros::{MacroRulesScope, sub_namespace_match};
use crate::{
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, CmResolver, Determinacy,
Finalize, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot,
NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError,
Resolver, Scope, ScopeSet, Segment, Stage, Used, Weak, errors,
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, AmbiguityWarning, BindingKey, CmResolver,
Determinacy, Finalize, ImportKind, LexicalScopeBinding, Module, ModuleKind,
ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res,
ResolutionError, Resolver, Scope, ScopeSet, Segment, Stage, Used, Weak, errors,
};

#[derive(Copy, Clone)]
Expand Down Expand Up @@ -644,11 +645,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
return None;
}

// preemptively look for ambiguities for panic macros to ensure we don't
// speculatively resolve to a non-prelude item when an ambiguity that we'd
// downgrade is present
let is_issue_147319_hack = || ctxt.edition()
<= Edition::Edition2024
&& matches!(orig_ident.name, sym::panic)
&& (this.is_specific_builtin_macro(binding.res(), sym::std_panic) || this.is_specific_builtin_macro(binding.res(), sym::core_panic));
let finalizing = !matches!(finalize, None | Some(Finalize { stage: Stage::Late, .. }));

// Below we report various ambiguity errors.
// We do not need to report them if we are either in speculative resolution,
// or in late resolution when everything is already imported and expanded
// and no ambiguities exist.
if matches!(finalize, None | Some(Finalize { stage: Stage::Late, .. })) {
if !finalizing && !is_issue_147319_hack() {
return Some(Ok(binding));
}

Expand Down Expand Up @@ -705,13 +715,41 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// Skip ambiguity errors for extern flag bindings "overridden"
// by extern item bindings.
// FIXME: Remove with lang team approval.
let issue_145575_hack = Some(binding)
== extern_prelude_flag_binding
&& extern_prelude_item_binding.is_some()
&& extern_prelude_item_binding != Some(innermost_binding);
let is_issue_145575_hack = || {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this changed to a closure to avoid evaluating the expression if kind is None?

Some(binding) == extern_prelude_flag_binding
&& extern_prelude_item_binding.is_some()
&& extern_prelude_item_binding != Some(innermost_binding)
};

if let Some(kind) = ambiguity_error_kind
&& !issue_145575_hack
&& !is_issue_145575_hack()
{
// Turn ambiguity errors for core vs std panic into warnings.
// FIXME: Remove with lang team approval.
let is_issue_147319_hack = ctxt.edition()
<= Edition::Edition2024
&& matches!(orig_ident.name, sym::panic)
&& matches!(scope, Scope::StdLibPrelude)
&& ((this.is_specific_builtin_macro(
binding.res(),
sym::std_panic,
) && this.is_specific_builtin_macro(
innermost_binding.res(),
sym::core_panic,
)) || (this.is_specific_builtin_macro(
binding.res(),
sym::core_panic,
) && this.is_specific_builtin_macro(
innermost_binding.res(),
sym::std_panic,
)));

let warning = if is_issue_147319_hack {
Some(AmbiguityWarning::PanicImport)
} else {
None
};

let misc = |f: Flags| {
if f.contains(Flags::MISC_SUGGEST_CRATE) {
AmbiguityErrorMisc::SuggestCrate
Expand All @@ -723,16 +761,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
AmbiguityErrorMisc::None
}
};
this.get_mut().ambiguity_errors.push(AmbiguityError {
kind,
ident: orig_ident,
b1: innermost_binding,
b2: binding,
warning: false,
misc1: misc(innermost_flags),
misc2: misc(flags),
});
return Some(Ok(innermost_binding));
if finalizing {
this.get_mut().ambiguity_errors.push(AmbiguityError {
kind,
ident: orig_ident,
b1: innermost_binding,
b2: binding,
warning,
misc1: misc(innermost_flags),
misc2: misc(flags),
});
}
if is_issue_147319_hack {
return Some(Ok(binding));
} else {
return Some(Ok(innermost_binding));
}
}
}
} else {
Expand Down Expand Up @@ -1072,7 +1116,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ident,
b1: binding,
b2: shadowed_glob,
warning: false,
warning: None,
misc1: AmbiguityErrorMisc::None,
misc2: AmbiguityErrorMisc::None,
});
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -945,8 +945,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ImportKind::Single { bindings, .. } => bindings[TypeNS].get().binding(),
_ => None,
};
let ambiguity_errors_len =
|errors: &Vec<AmbiguityError<'_>>| errors.iter().filter(|error| !error.warning).count();
let ambiguity_errors_len = |errors: &Vec<AmbiguityError<'_>>| {
errors.iter().filter(|error| error.warning.is_none()).count()
};
let prev_ambiguity_errors_len = ambiguity_errors_len(&self.ambiguity_errors);
let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span);

Expand Down Expand Up @@ -1161,7 +1162,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
});
let res = binding.res();
let has_ambiguity_error =
this.ambiguity_errors.iter().any(|error| !error.warning);
this.ambiguity_errors.iter().any(|error| error.warning.is_none());
if res == Res::Err || has_ambiguity_error {
this.dcx()
.span_delayed_bug(import.span, "some error happened for an import");
Expand Down
14 changes: 12 additions & 2 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -907,14 +907,20 @@ enum AmbiguityErrorMisc {
None,
}

#[derive(Clone, Copy, PartialEq)]
enum AmbiguityWarning {
GlobImport,
PanicImport,
}

struct AmbiguityError<'ra> {
kind: AmbiguityKind,
ident: Ident,
b1: NameBinding<'ra>,
b2: NameBinding<'ra>,
misc1: AmbiguityErrorMisc,
misc2: AmbiguityErrorMisc,
warning: bool,
warning: Option<AmbiguityWarning>,
}

impl<'ra> NameBindingData<'ra> {
Expand Down Expand Up @@ -1851,6 +1857,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
self.get_macro(res).is_some_and(|macro_data| macro_data.ext.builtin_name.is_some())
}

fn is_specific_builtin_macro(&self, res: Res, symbol: Symbol) -> bool {
self.get_macro(res).is_some_and(|macro_data| macro_data.ext.builtin_name == Some(symbol))
}

fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
loop {
match ctxt.outer_expn_data().macro_def_id {
Expand Down Expand Up @@ -2042,7 +2052,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
b2,
misc1: AmbiguityErrorMisc::None,
misc2: AmbiguityErrorMisc::None,
warning: warn_ambiguity,
warning: if warn_ambiguity { Some(AmbiguityWarning::GlobImport) } else { None },
};
if !self.matches_previous_ambiguity_error(&ambiguity_error) {
// avoid duplicated span information to be emit out
Expand Down
17 changes: 13 additions & 4 deletions compiler/rustc_resolve/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -838,10 +838,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
res: Res| {
if let Some(initial_res) = initial_res {
if res != initial_res {
// Make sure compilation does not succeed if preferred macro resolution
// has changed after the macro had been expanded. In theory all such
// situations should be reported as errors, so this is a bug.
this.dcx().span_delayed_bug(span, "inconsistent resolution for a macro");
// Delayed versions of the #147319 workaround are inconsistent, but not really
// problematic and already seen as a bug.
// FIXME: Remove with lang team approval.
if !this
.ambiguity_errors
.iter()
.all(|ambiguity_error| ambiguity_error.warning.is_some())
{
// Make sure compilation does not succeed if preferred macro resolution
// has changed after the macro had been expanded. In theory all such
// situations should be reported as errors, so this is a bug.
this.dcx().span_delayed_bug(span, "inconsistent resolution for a macro");
}
}
} else if this.tcx.dcx().has_errors().is_none() && this.privacy_errors.is_empty() {
// It's possible that the macro was unresolved (indeterminate) and silently
Expand Down
12 changes: 9 additions & 3 deletions library/alloctests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(optimize_attribute)]
#![feature(prelude_import)]
#![feature(rustc_allow_const_fn_unstable)]
#![feature(rustc_attrs)]
#![feature(staged_api)]
Expand All @@ -68,11 +69,17 @@

// Allow testing this library
extern crate alloc as realalloc;
#[macro_use]

// This is needed to provide macros to the directly imported alloc modules below.
extern crate std;
#[prelude_import]
#[allow(unused_imports)]
use std::prelude::rust_2024::*;

#[cfg(test)]
extern crate test;
mod testing;

use realalloc::*;

// We are directly including collections, raw_vec, and wtf8 here as they use non-public
Expand All @@ -96,8 +103,7 @@ pub(crate) mod test_helpers {
let mut hasher = std::hash::RandomState::new().build_hasher();
std::panic::Location::caller().hash(&mut hasher);
let hc64 = hasher.finish();
let seed_vec =
hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<crate::vec::Vec<u8>>();
let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<std::vec::Vec<u8>>();
let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap();
rand::SeedableRng::from_seed(seed)
}
Expand Down
Loading