From 6c865c1e14d5bd76b4ffe1e7ed2e60b3261d03a9 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 17 Mar 2025 16:50:55 +0100 Subject: [PATCH] Allow builtin macros to be used more than once. This removes E0773 "A builtin-macro was defined more than once." --- compiler/rustc_builtin_macros/src/lib.rs | 14 ++++--- .../src/error_codes/E0773.md | 42 ++----------------- compiler/rustc_expand/src/base.rs | 21 +++++----- compiler/rustc_expand/src/mbe/macro_rules.rs | 5 ++- compiler/rustc_metadata/src/rmeta/decoder.rs | 6 +-- compiler/rustc_resolve/messages.ftl | 4 -- compiler/rustc_resolve/src/errors.rs | 9 ---- compiler/rustc_resolve/src/lib.rs | 8 +--- compiler/rustc_resolve/src/macros.rs | 23 ++++------ tests/ui/macros/duplicate-builtin.rs | 17 -------- tests/ui/macros/duplicate-builtin.stderr | 21 ---------- tests/ui/macros/unknown-builtin.rs | 5 +-- tests/ui/macros/unknown-builtin.stderr | 14 +------ 13 files changed, 40 insertions(+), 149 deletions(-) delete mode 100644 tests/ui/macros/duplicate-builtin.rs delete mode 100644 tests/ui/macros/duplicate-builtin.stderr diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index dab3053d8b0..606e85577f7 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -23,6 +23,8 @@ extern crate proc_macro; +use std::sync::Arc; + use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind}; use rustc_expand::proc_macro::BangProcMacro; use rustc_span::sym; @@ -67,13 +69,13 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { let mut register = |name, kind| resolver.register_builtin_macro(name, kind); macro register_bang($($name:ident: $f:expr,)*) { - $(register(sym::$name, SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)));)* + $(register(sym::$name, SyntaxExtensionKind::LegacyBang(Arc::new($f as MacroExpanderFn)));)* } macro register_attr($($name:ident: $f:expr,)*) { - $(register(sym::$name, SyntaxExtensionKind::LegacyAttr(Box::new($f)));)* + $(register(sym::$name, SyntaxExtensionKind::LegacyAttr(Arc::new($f)));)* } macro register_derive($($name:ident: $f:expr,)*) { - $(register(sym::$name, SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($f))));)* + $(register(sym::$name, SyntaxExtensionKind::LegacyDerive(Arc::new(BuiltinDerive($f))));)* } register_bang! { @@ -139,9 +141,9 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { } let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); - register(sym::quote, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client }))); - let requires = SyntaxExtensionKind::Attr(Box::new(contracts::ExpandRequires)); + register(sym::quote, SyntaxExtensionKind::Bang(Arc::new(BangProcMacro { client }))); + let requires = SyntaxExtensionKind::Attr(Arc::new(contracts::ExpandRequires)); register(sym::contracts_requires, requires); - let ensures = SyntaxExtensionKind::Attr(Box::new(contracts::ExpandEnsures)); + let ensures = SyntaxExtensionKind::Attr(Arc::new(contracts::ExpandEnsures)); register(sym::contracts_ensures, ensures); } diff --git a/compiler/rustc_error_codes/src/error_codes/E0773.md b/compiler/rustc_error_codes/src/error_codes/E0773.md index aa65a475a4f..5ebb43c6683 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0773.md +++ b/compiler/rustc_error_codes/src/error_codes/E0773.md @@ -1,40 +1,4 @@ -A builtin-macro was defined more than once. +#### this error code is no longer emitted by the compiler. -Erroneous code example: - -```compile_fail,E0773 -#![feature(decl_macro)] -#![feature(rustc_attrs)] -#![allow(internal_features)] - -#[rustc_builtin_macro] -pub macro test($item:item) { - /* compiler built-in */ -} - -mod inner { - #[rustc_builtin_macro] - pub macro test($item:item) { - /* compiler built-in */ - } -} -``` - -To fix the issue, remove the duplicate declaration: - -``` -#![feature(decl_macro)] -#![feature(rustc_attrs)] -#![allow(internal_features)] - -#[rustc_builtin_macro] -pub macro test($item:item) { - /* compiler built-in */ -} -``` - -In very rare edge cases, this may happen when loading `core` or `std` twice, -once with `check` metadata and once with `build` metadata. -For more information, see [#75176]. - -[#75176]: https://github.com/rust-lang/rust/pull/75176#issuecomment-683234468 +This was triggered when multiple macro definitions used the same +`#[rustc_builtin_macro(..)]`. This is no longer an error. diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index c4b53962584..1dd152beb47 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -681,17 +681,18 @@ impl MacResult for DummyResult { } /// A syntax extension kind. +#[derive(Clone)] pub enum SyntaxExtensionKind { /// A token-based function-like macro. Bang( /// An expander with signature TokenStream -> TokenStream. - Box, + Arc, ), /// An AST-based function-like macro. LegacyBang( /// An expander with signature TokenStream -> AST. - Box, + Arc, ), /// A token-based attribute macro. @@ -699,7 +700,7 @@ pub enum SyntaxExtensionKind { /// An expander with signature (TokenStream, TokenStream) -> TokenStream. /// The first TokenStream is the attribute itself, the second is the annotated item. /// The produced TokenStream replaces the input TokenStream. - Box, + Arc, ), /// An AST-based attribute macro. @@ -707,7 +708,7 @@ pub enum SyntaxExtensionKind { /// An expander with signature (AST, AST) -> AST. /// The first AST fragment is the attribute itself, the second is the annotated item. /// The produced AST fragment replaces the input AST fragment. - Box, + Arc, ), /// A trivial attribute "macro" that does nothing, @@ -724,18 +725,18 @@ pub enum SyntaxExtensionKind { /// is handled identically to `LegacyDerive`. It should be migrated to /// a token-based representation like `Bang` and `Attr`, instead of /// using `MultiItemModifier`. - Box, + Arc, ), /// An AST-based derive macro. LegacyDerive( /// An expander with signature AST -> AST. /// The produced AST fragment is appended to the input AST fragment. - Box, + Arc, ), /// A glob delegation. - GlobDelegation(Box), + GlobDelegation(Arc), } /// A struct representing a macro definition in "lowered" form ready for expansion. @@ -937,7 +938,7 @@ impl SyntaxExtension { cx.dcx().span_delayed_bug(span, "expanded a dummy bang macro"), )) } - SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Box::new(expander)), edition) + SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Arc::new(expander)), edition) } /// A dummy derive macro `#[derive(Foo)]`. @@ -950,7 +951,7 @@ impl SyntaxExtension { ) -> Vec { Vec::new() } - SyntaxExtension::default(SyntaxExtensionKind::Derive(Box::new(expander)), edition) + SyntaxExtension::default(SyntaxExtensionKind::Derive(Arc::new(expander)), edition) } pub fn non_macro_attr(edition: Edition) -> SyntaxExtension { @@ -980,7 +981,7 @@ impl SyntaxExtension { } let expander = GlobDelegationExpanderImpl { trait_def_id, impl_def_id }; - SyntaxExtension::default(SyntaxExtensionKind::GlobDelegation(Box::new(expander)), edition) + SyntaxExtension::default(SyntaxExtensionKind::GlobDelegation(Arc::new(expander)), edition) } pub fn expn_data( diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 5577c8902da..77ec598e62a 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::collections::hash_map::Entry; +use std::sync::Arc; use std::{mem, slice}; use ast::token::IdentIsRaw; @@ -388,7 +389,7 @@ pub fn compile_declarative_macro( node_id != DUMMY_NODE_ID, ) }; - let dummy_syn_ext = |guar| (mk_syn_ext(Box::new(DummyExpander(guar))), Vec::new()); + let dummy_syn_ext = |guar| (mk_syn_ext(Arc::new(DummyExpander(guar))), Vec::new()); let lhs_nm = Ident::new(sym::lhs, span); let rhs_nm = Ident::new(sym::rhs, span); @@ -582,7 +583,7 @@ pub fn compile_declarative_macro( }) .collect(); - let expander = Box::new(MacroRulesMacroExpander { + let expander = Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index e60904eebeb..f6cf218db9d 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1053,15 +1053,15 @@ impl<'a> CrateMetadataRef<'a> { attributes.iter().cloned().map(Symbol::intern).collect::>(); ( trait_name, - SyntaxExtensionKind::Derive(Box::new(DeriveProcMacro { client })), + SyntaxExtensionKind::Derive(Arc::new(DeriveProcMacro { client })), helper_attrs, ) } ProcMacro::Attr { name, client } => { - (name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new()) + (name, SyntaxExtensionKind::Attr(Arc::new(AttrProcMacro { client })), Vec::new()) } ProcMacro::Bang { name, client } => { - (name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()) + (name, SyntaxExtensionKind::Bang(Arc::new(BangProcMacro { client })), Vec::new()) } }; diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 817aa5b4385..558a01713dc 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -26,10 +26,6 @@ resolve_associated_fn_with_similar_name_exists = resolve_associated_type_with_similar_name_exists = there is an associated type with a similar name -resolve_attempt_to_define_builtin_macro_twice = - attempted to define built-in macro more than once - .note = previously defined here - resolve_attempt_to_use_non_constant_value_in_constant = attempt to use a non-constant value in a constant diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 2ae6892bc93..e26b300f13e 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -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 { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 447d5283e27..ff31af0025b 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1010,12 +1010,6 @@ impl ExternPreludeEntry<'_> { } } -/// Used for better errors for E0773 -enum BuiltinMacroState { - NotYetSeen(SyntaxExtensionKind), - AlreadySeen(Span), -} - struct DeriveData { resolutions: Vec, helper_attrs: Vec<(usize, Ident)>, @@ -1134,7 +1128,7 @@ pub struct Resolver<'ra, 'tcx> { used_extern_options: FxHashSet, macro_names: FxHashSet, - builtin_macros: FxHashMap, + builtin_macros: FxHashMap, registered_tools: &'tcx RegisteredTools, macro_use_prelude: FxIndexMap>, macro_map: FxHashMap, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 7100d89ad61..c94846e95d4 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -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; @@ -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 }); } diff --git a/tests/ui/macros/duplicate-builtin.rs b/tests/ui/macros/duplicate-builtin.rs deleted file mode 100644 index c75782128f4..00000000000 --- a/tests/ui/macros/duplicate-builtin.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ compile-flags:--crate-type lib -#![feature(decl_macro)] -#![feature(rustc_attrs)] - -#[rustc_builtin_macro] -pub macro test($item:item) { -//~^ NOTE previously defined - /* compiler built-in */ -} - -mod inner { - #[rustc_builtin_macro] - pub macro test($item:item) { - //~^ ERROR attempted to define built-in macro more than once [E0773] - /* compiler built-in */ - } -} diff --git a/tests/ui/macros/duplicate-builtin.stderr b/tests/ui/macros/duplicate-builtin.stderr deleted file mode 100644 index 887a4fbbdc8..00000000000 --- a/tests/ui/macros/duplicate-builtin.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0773]: attempted to define built-in macro more than once - --> $DIR/duplicate-builtin.rs:13:5 - | -LL | / pub macro test($item:item) { -LL | | -LL | | /* compiler built-in */ -LL | | } - | |_____^ - | -note: previously defined here - --> $DIR/duplicate-builtin.rs:6:1 - | -LL | / pub macro test($item:item) { -LL | | -LL | | /* compiler built-in */ -LL | | } - | |_^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0773`. diff --git a/tests/ui/macros/unknown-builtin.rs b/tests/ui/macros/unknown-builtin.rs index 048f5d68d34..aa6e04d3fb8 100644 --- a/tests/ui/macros/unknown-builtin.rs +++ b/tests/ui/macros/unknown-builtin.rs @@ -1,12 +1,11 @@ -//@ error-pattern: attempted to define built-in macro more than once - #![feature(rustc_attrs)] #[rustc_builtin_macro] macro_rules! unknown { () => () } //~ ERROR cannot find a built-in macro with name `unknown` +// Defining another `line` builtin macro should not cause an error. #[rustc_builtin_macro] -macro_rules! line { () => () } //~ NOTE previously defined here +macro_rules! line { () => () } fn main() { line!(); diff --git a/tests/ui/macros/unknown-builtin.stderr b/tests/ui/macros/unknown-builtin.stderr index 22f54e04e54..1a83398891b 100644 --- a/tests/ui/macros/unknown-builtin.stderr +++ b/tests/ui/macros/unknown-builtin.stderr @@ -1,18 +1,8 @@ error: cannot find a built-in macro with name `unknown` - --> $DIR/unknown-builtin.rs:6:1 + --> $DIR/unknown-builtin.rs:4:1 | LL | macro_rules! unknown { () => () } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0773]: attempted to define built-in macro more than once - --> $SRC_DIR/core/src/macros/mod.rs:LL:COL - | -note: previously defined here - --> $DIR/unknown-builtin.rs:9:1 - | -LL | macro_rules! line { () => () } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0773`.