diff options
| author | Boxy <rust@boxyuwu.dev> | 2025-02-25 21:27:44 +0000 |
|---|---|---|
| committer | Boxy <rust@boxyuwu.dev> | 2025-02-25 21:27:44 +0000 |
| commit | d9683df7c2f6d4141b1321e27635d2ce3167eaa4 (patch) | |
| tree | dce0d46d1b7d624ec9b9b09b2c1854f6245a5ff4 /compiler/rustc_macros | |
| parent | 46392d1661540e256fd9573d8f06c2784a58c983 (diff) | |
| parent | 4ecd70ddd1039a3954056c1071e40278048476fa (diff) | |
| download | rust-d9683df7c2f6d4141b1321e27635d2ce3167eaa4.tar.gz rust-d9683df7c2f6d4141b1321e27635d2ce3167eaa4.zip | |
Merge from rustc
Diffstat (limited to 'compiler/rustc_macros')
| -rw-r--r-- | compiler/rustc_macros/Cargo.toml | 2 | ||||
| -rw-r--r-- | compiler/rustc_macros/src/diagnostics/utils.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_macros/src/lib.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_macros/src/print_attribute.rs | 145 | ||||
| -rw-r--r-- | compiler/rustc_macros/src/type_visitable.rs | 6 |
5 files changed, 160 insertions, 6 deletions
diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml index d8d2bef4964..f9d3b758359 100644 --- a/compiler/rustc_macros/Cargo.toml +++ b/compiler/rustc_macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_macros" version = "0.0.0" -edition = "2021" +edition = "2024" [lib] proc-macro = true diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 612a36ba9aa..060799e981d 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -760,8 +760,8 @@ impl SubdiagnosticVariant { } ( "applicability", - SubdiagnosticKind::Suggestion { ref mut applicability, .. } - | SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. }, + SubdiagnosticKind::Suggestion { applicability, .. } + | SubdiagnosticKind::MultipartSuggestion { applicability, .. }, ) => { let value = get_string!(); let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| { diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 0df674eb4c9..34fc0f00320 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -17,6 +17,7 @@ mod diagnostics; mod extension; mod hash_stable; mod lift; +mod print_attribute; mod query; mod serialize; mod symbols; @@ -175,3 +176,11 @@ decl_derive! { /// The error type is `u32`. try_from::try_from_u32 } +decl_derive! { + [PrintAttribute] => + /// Derives `PrintAttribute` for `AttributeKind`. + /// This macro is pretty specific to `rustc_attr_data_structures` and likely not that useful in + /// other places. It's deriving something close to `Debug` without printing some extraenous + /// things like spans. + print_attribute::print_attribute +} diff --git a/compiler/rustc_macros/src/print_attribute.rs b/compiler/rustc_macros/src/print_attribute.rs new file mode 100644 index 00000000000..3c6e30b851b --- /dev/null +++ b/compiler/rustc_macros/src/print_attribute.rs @@ -0,0 +1,145 @@ +use proc_macro2::TokenStream; +use quote::{format_ident, quote, quote_spanned}; +use syn::spanned::Spanned; +use syn::{Data, Fields, Ident}; +use synstructure::Structure; + +fn print_fields(name: &Ident, fields: &Fields) -> (TokenStream, TokenStream, TokenStream) { + let string_name = name.to_string(); + let mut disps = vec![quote! {let mut __printed_anything = false;}]; + + match fields { + Fields::Named(fields_named) => { + let mut field_names = Vec::new(); + + for field in &fields_named.named { + let name = field.ident.as_ref().unwrap(); + let string_name = name.to_string(); + disps.push(quote! { + if __printed_anything && #name.print_something() { + __p.word_space(","); + __printed_anything = true; + } + __p.word(#string_name); + __p.word_space(":"); + #name.print_attribute(__p); + }); + field_names.push(name); + } + + ( + quote! { {#(#field_names),*} }, + quote! { + __p.word(#string_name); + if true #(&& !#field_names.print_something())* { + return; + } + + __p.word("{"); + #(#disps)* + __p.word("}"); + }, + quote! { true }, + ) + } + Fields::Unnamed(fields_unnamed) => { + let mut field_names = Vec::new(); + + for idx in 0..fields_unnamed.unnamed.len() { + let name = format_ident!("f{idx}"); + disps.push(quote! { + if __printed_anything && #name.print_something() { + __p.word_space(","); + __printed_anything = true; + } + #name.print_attribute(__p); + }); + field_names.push(name); + } + + ( + quote! { (#(#field_names),*) }, + quote! { + __p.word(#string_name); + + if true #(&& !#field_names.print_something())* { + return; + } + + __p.word("("); + #(#disps)* + __p.word(")"); + }, + quote! { true }, + ) + } + Fields::Unit => (quote! {}, quote! { __p.word(#string_name) }, quote! { true }), + } +} + +pub(crate) fn print_attribute(input: Structure<'_>) -> TokenStream { + let span_error = |span, message: &str| { + quote_spanned! { span => const _: () = ::core::compile_error!(#message); } + }; + + // Must be applied to an enum type. + let (code, printed) = match &input.ast().data { + Data::Enum(e) => { + let (arms, printed) = e + .variants + .iter() + .map(|x| { + let ident = &x.ident; + let (pat, code, printed) = print_fields(ident, &x.fields); + + ( + quote! { + Self::#ident #pat => {#code} + }, + quote! { + Self::#ident #pat => {#printed} + }, + ) + }) + .unzip::<_, _, Vec<_>, Vec<_>>(); + + ( + quote! { + match self { + #(#arms)* + } + }, + quote! { + match self { + #(#printed)* + } + }, + ) + } + Data::Struct(s) => { + let (pat, code, printed) = print_fields(&input.ast().ident, &s.fields); + ( + quote! { + let Self #pat = self; + #code + }, + quote! { + let Self #pat = self; + #printed + }, + ) + } + Data::Union(u) => { + return span_error(u.union_token.span(), "can't derive PrintAttribute on unions"); + } + }; + + #[allow(keyword_idents_2024)] + input.gen_impl(quote! { + #[allow(unused)] + gen impl PrintAttribute for @Self { + fn print_something(&self) -> bool { #printed } + fn print_attribute(&self, __p: &mut rustc_ast_pretty::pp::Printer) { #code } + } + }) +} diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs index 527ca26c0eb..a7906d50d0f 100644 --- a/compiler/rustc_macros/src/type_visitable.rs +++ b/compiler/rustc_macros/src/type_visitable.rs @@ -36,12 +36,12 @@ pub(super) fn type_visitable_derive( s.add_bounds(synstructure::AddBounds::Generics); let body_visit = s.each(|bind| { quote! { - match ::rustc_ast_ir::visit::VisitorResult::branch( + match ::rustc_middle::ty::visit::VisitorResult::branch( ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor) ) { ::core::ops::ControlFlow::Continue(()) => {}, ::core::ops::ControlFlow::Break(r) => { - return ::rustc_ast_ir::visit::VisitorResult::from_residual(r); + return ::rustc_middle::ty::visit::VisitorResult::from_residual(r); }, } } @@ -56,7 +56,7 @@ pub(super) fn type_visitable_derive( __visitor: &mut __V ) -> __V::Result { match *self { #body_visit } - <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output() + <__V::Result as ::rustc_middle::ty::visit::VisitorResult>::output() } }, ) |
