From 02638a39a394c9995ef94aecfd6ae2a76599d4d2 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Sat, 10 Aug 2024 21:11:07 +0800 Subject: [PATCH] derive(SmartPointer): register helper attributes --- compiler/rustc_builtin_macros/src/lib.rs | 15 +++++-- compiler/rustc_expand/src/base.rs | 2 + compiler/rustc_expand/src/expand.rs | 2 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 4 +- compiler/rustc_feature/src/builtin_attrs.rs | 6 --- compiler/rustc_resolve/src/macros.rs | 7 +++ .../deriving/auxiliary/another-proc-macro.rs | 32 ++++++++++++++ .../ui/deriving/built-in-proc-macro-scope.rs | 25 +++++++++++ .../deriving/built-in-proc-macro-scope.stdout | 43 +++++++++++++++++++ .../feature-gate-derive-smart-pointer.rs | 1 - .../feature-gate-derive-smart-pointer.stderr | 12 +----- 11 files changed, 125 insertions(+), 24 deletions(-) create mode 100644 tests/ui/deriving/auxiliary/another-proc-macro.rs create mode 100644 tests/ui/deriving/built-in-proc-macro-scope.rs create mode 100644 tests/ui/deriving/built-in-proc-macro-scope.stdout diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index a9ba7334d930e..735fa229e8413 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -23,6 +23,7 @@ extern crate proc_macro; use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind}; use rustc_expand::proc_macro::BangProcMacro; use rustc_span::symbol::sym; +use smallvec::smallvec; use crate::deriving::*; @@ -66,8 +67,16 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { macro register_attr($($name:ident: $f:expr,)*) { $(register(sym::$name, SyntaxExtensionKind::LegacyAttr(Box::new($f)));)* } - macro register_derive($($name:ident: $f:expr,)*) { - $(register(sym::$name, SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($f))));)* + macro_rules! register_derive { + ($name:ident: $f:expr, $($rest:tt)*) => { + register(sym::$name, SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($f)), smallvec![])); + register_derive!($($rest)*); + }; + ($name:ident(attrs = [$($attr:ident),+]): $f:expr, $($rest:tt)*) => { + register(sym::$name, SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($f)), smallvec![$(sym::$attr),*])); + register_derive!($($rest)*); + }; + () => {}; } register_bang! { @@ -128,7 +137,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { PartialOrd: partial_ord::expand_deriving_partial_ord, RustcDecodable: decodable::expand_deriving_rustc_decodable, RustcEncodable: encodable::expand_deriving_rustc_encodable, - SmartPointer: smart_ptr::expand_deriving_smart_ptr, + SmartPointer(attrs = [pointee]): smart_ptr::expand_deriving_smart_ptr, } let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index c195d69258899..7172e74388f92 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -714,6 +714,8 @@ pub enum SyntaxExtensionKind { /// An expander with signature AST -> AST. /// The produced AST fragment is appended to the input AST fragment. Box, + /// Helper attributes + SmallVec<[Symbol; 1]>, ), /// A glob delegation. diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index d8cb367e3face..a61b3389e678c 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -781,7 +781,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }, InvocationKind::Derive { path, item, is_const } => match ext { SyntaxExtensionKind::Derive(expander) - | SyntaxExtensionKind::LegacyDerive(expander) => { + | SyntaxExtensionKind::LegacyDerive(expander, _) => { if let SyntaxExtensionKind::Derive(..) = ext { self.gate_proc_macro_input(&item); } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 6f177107e7025..fc0c328819caf 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -366,14 +366,14 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>( // // Holy self-referential! -/// Converts a macro item into a syntax extension. +/// Converts a macro item `def` into a syntax extension. +#[instrument(level = "debug", skip(sess, features))] pub fn compile_declarative_macro( sess: &Session, features: &Features, def: &ast::Item, edition: Edition, ) -> (SyntaxExtension, Vec<(usize, Span)>) { - debug!("compile_declarative_macro: {:?}", def); let mk_syn_ext = |expander| { SyntaxExtension::new( sess, diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 72ea55d5999a2..bb0e989bd812a 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -578,12 +578,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::No, coroutines, experimental!(coroutines) ), - // `#[pointee]` attribute to designate the pointee type in SmartPointer derive-macro - gated!( - pointee, Normal, template!(Word), ErrorFollowing, - EncodeCrossCrate::No, derive_smart_pointer, experimental!(pointee) - ), - // RFC 3543 // `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` gated!( diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index da7278175e93a..4b5919f8365f3 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -34,6 +34,7 @@ use rustc_span::edition::Edition; use rustc_span::hygiene::{self, AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; +use tracing::instrument; use crate::errors::{ self, AddAsNonDerive, CannotDetermineMacroResolution, CannotFindIdentInThisScope, @@ -1117,6 +1118,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Compile the macro into a `SyntaxExtension` and its rule spans. /// /// Possibly replace its expander to a pre-defined one for built-in macros. + #[instrument(level = "debug", skip(self))] pub(crate) fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> MacroData { let (mut ext, mut rule_spans) = compile_declarative_macro(self.tcx.sess, self.tcx.features(), item, edition); @@ -1129,6 +1131,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // If we already loaded this builtin macro, give a better error message than 'no such builtin macro'. match mem::replace(builtin_macro, BuiltinMacroState::AlreadySeen(item.span)) { BuiltinMacroState::NotYetSeen(builtin_ext) => { + if let SyntaxExtensionKind::LegacyDerive(_expander, helper_attrs) = + &builtin_ext + { + ext.helper_attrs.extend(helper_attrs.iter().copied()); + } ext.kind = builtin_ext; rule_spans = Vec::new(); } diff --git a/tests/ui/deriving/auxiliary/another-proc-macro.rs b/tests/ui/deriving/auxiliary/another-proc-macro.rs new file mode 100644 index 0000000000000..fc94e29445023 --- /dev/null +++ b/tests/ui/deriving/auxiliary/another-proc-macro.rs @@ -0,0 +1,32 @@ +//@ force-host +//@ no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::{quote, TokenStream}; + +#[proc_macro_derive(AnotherMacro, attributes(pointee))] +pub fn derive(_input: TokenStream) -> TokenStream { + quote! { + const _: () = { + const ANOTHER_MACRO_DERIVED: () = (); + }; + } + .into() +} + +#[proc_macro_attribute] +pub fn pointee( + _attr: proc_macro::TokenStream, + _item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + quote! { + const _: () = { + const ANOTHER_MACRO_ATTR_DERIVED: () = (); + }; + } + .into() +} diff --git a/tests/ui/deriving/built-in-proc-macro-scope.rs b/tests/ui/deriving/built-in-proc-macro-scope.rs new file mode 100644 index 0000000000000..41c95f63b135e --- /dev/null +++ b/tests/ui/deriving/built-in-proc-macro-scope.rs @@ -0,0 +1,25 @@ +//@ check-pass +//@ aux-build: another-proc-macro.rs +//@ compile-flags: -Zunpretty=expanded + +#![feature(derive_smart_pointer)] + +#[macro_use] +extern crate another_proc_macro; + +use another_proc_macro::{pointee, AnotherMacro}; + +#[derive(core::marker::SmartPointer)] +#[repr(transparent)] +pub struct Ptr<'a, #[pointee] T: ?Sized> { + data: &'a mut T, +} + +#[pointee] +fn f() {} + +#[derive(AnotherMacro)] +#[pointee] +struct MyStruct; + +fn main() {} diff --git a/tests/ui/deriving/built-in-proc-macro-scope.stdout b/tests/ui/deriving/built-in-proc-macro-scope.stdout new file mode 100644 index 0000000000000..2e2cdc7b434a7 --- /dev/null +++ b/tests/ui/deriving/built-in-proc-macro-scope.stdout @@ -0,0 +1,43 @@ +#![feature(prelude_import)] +#![no_std] +//@ check-pass +//@ aux-build: another-proc-macro.rs +//@ compile-flags: -Zunpretty=expanded + +#![feature(derive_smart_pointer)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +#[macro_use] +extern crate another_proc_macro; + +use another_proc_macro::{pointee, AnotherMacro}; + +#[repr(transparent)] +pub struct Ptr<'a, #[pointee] T: ?Sized> { + data: &'a mut T, +} +#[automatically_derived] +impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> + ::core::ops::DispatchFromDyn> for Ptr<'a, T> { +} +#[automatically_derived] +impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> + ::core::ops::CoerceUnsized> for Ptr<'a, T> { +} + + + +const _: () = + { + const ANOTHER_MACRO_ATTR_DERIVED: () = (); + }; +#[pointee] +struct MyStruct; +const _: () = + { + const ANOTHER_MACRO_DERIVED: () = (); + }; +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-derive-smart-pointer.rs b/tests/ui/feature-gates/feature-gate-derive-smart-pointer.rs index 3257a9ca624ba..7b4764ee768ab 100644 --- a/tests/ui/feature-gates/feature-gate-derive-smart-pointer.rs +++ b/tests/ui/feature-gates/feature-gate-derive-smart-pointer.rs @@ -3,7 +3,6 @@ use std::marker::SmartPointer; //~ ERROR use of unstable library feature 'derive #[derive(SmartPointer)] //~ ERROR use of unstable library feature 'derive_smart_pointer' #[repr(transparent)] struct MyPointer<'a, #[pointee] T: ?Sized> { - //~^ ERROR the `#[pointee]` attribute is an experimental feature ptr: &'a T, } diff --git a/tests/ui/feature-gates/feature-gate-derive-smart-pointer.stderr b/tests/ui/feature-gates/feature-gate-derive-smart-pointer.stderr index 19501939dc5be..ea4d1271b7c87 100644 --- a/tests/ui/feature-gates/feature-gate-derive-smart-pointer.stderr +++ b/tests/ui/feature-gates/feature-gate-derive-smart-pointer.stderr @@ -8,16 +8,6 @@ LL | #[derive(SmartPointer)] = help: add `#![feature(derive_smart_pointer)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: the `#[pointee]` attribute is an experimental feature - --> $DIR/feature-gate-derive-smart-pointer.rs:5:22 - | -LL | struct MyPointer<'a, #[pointee] T: ?Sized> { - | ^^^^^^^^^^ - | - = note: see issue #123430 for more information - = help: add `#![feature(derive_smart_pointer)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0658]: use of unstable library feature 'derive_smart_pointer' --> $DIR/feature-gate-derive-smart-pointer.rs:1:5 | @@ -28,6 +18,6 @@ LL | use std::marker::SmartPointer; = help: add `#![feature(derive_smart_pointer)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`.