Allow builtin macros to be used more than once.

This removes E0773 "A builtin-macro was defined more than once."
This commit is contained in:
Mara Bos 2025-03-17 16:50:55 +01:00
parent 1370611c0a
commit 6c865c1e14
13 changed files with 40 additions and 149 deletions

View file

@ -965,15 +965,6 @@ pub(crate) struct StaticLifetimeIsReserved {
pub(crate) lifetime: Ident,
}
#[derive(Diagnostic)]
#[diag(resolve_attempt_to_define_builtin_macro_twice, code = E0773)]
pub(crate) struct AttemptToDefineBuiltinMacroTwice {
#[primary_span]
pub(crate) span: Span,
#[note]
pub(crate) note_span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_variable_is_not_bound_in_all_patterns, code = E0408)]
pub(crate) struct VariableIsNotBoundInAllPatterns {

View file

@ -1010,12 +1010,6 @@ impl ExternPreludeEntry<'_> {
}
}
/// Used for better errors for E0773
enum BuiltinMacroState {
NotYetSeen(SyntaxExtensionKind),
AlreadySeen(Span),
}
struct DeriveData {
resolutions: Vec<DeriveResolution>,
helper_attrs: Vec<(usize, Ident)>,
@ -1134,7 +1128,7 @@ pub struct Resolver<'ra, 'tcx> {
used_extern_options: FxHashSet<Symbol>,
macro_names: FxHashSet<Ident>,
builtin_macros: FxHashMap<Symbol, BuiltinMacroState>,
builtin_macros: FxHashMap<Symbol, SyntaxExtensionKind>,
registered_tools: &'tcx RegisteredTools,
macro_use_prelude: FxIndexMap<Symbol, NameBinding<'ra>>,
macro_map: FxHashMap<DefId, MacroData>,

View file

@ -40,9 +40,9 @@ use crate::errors::{
};
use crate::imports::Import;
use crate::{
BindingKey, BuiltinMacroState, DeriveData, Determinacy, Finalize, InvocationParent, MacroData,
ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult,
ResolutionError, Resolver, ScopeSet, Segment, ToNameBinding, Used,
BindingKey, DeriveData, Determinacy, Finalize, InvocationParent, MacroData, ModuleKind,
ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError,
Resolver, ScopeSet, Segment, ToNameBinding, Used,
};
type Res = def::Res<NodeId>;
@ -194,7 +194,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
}
fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind) {
if self.builtin_macros.insert(name, BuiltinMacroState::NotYetSeen(ext)).is_some() {
if self.builtin_macros.insert(name, ext).is_some() {
self.dcx().bug(format!("built-in macro `{name}` was already registered"));
}
}
@ -1127,20 +1127,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
if let Some(builtin_name) = ext.builtin_name {
// The macro was marked with `#[rustc_builtin_macro]`.
if let Some(builtin_macro) = self.builtin_macros.get_mut(&builtin_name) {
if let Some(builtin_ext_kind) = self.builtin_macros.get(&builtin_name) {
// The macro is a built-in, replace its expander function
// while still taking everything else from the source code.
// If we already loaded this builtin macro, give a better error message than 'no such builtin macro'.
match mem::replace(builtin_macro, BuiltinMacroState::AlreadySeen(span)) {
BuiltinMacroState::NotYetSeen(builtin_ext) => {
ext.kind = builtin_ext;
rule_spans = Vec::new();
}
BuiltinMacroState::AlreadySeen(note_span) => {
self.dcx()
.emit_err(errors::AttemptToDefineBuiltinMacroTwice { span, note_span });
}
}
ext.kind = builtin_ext_kind.clone();
rule_spans = Vec::new();
} else {
self.dcx().emit_err(errors::CannotFindBuiltinMacroWithName { span, ident });
}