| 1 | // tidy-alphabetical-start |
| 2 | #![allow (rustc::default_hash_types)] |
| 3 | #![feature (if_let_guard)] |
| 4 | #![feature (let_chains)] |
| 5 | #![feature (never_type)] |
| 6 | #![feature (proc_macro_diagnostic)] |
| 7 | #![feature (proc_macro_span)] |
| 8 | #![feature (proc_macro_tracked_env)] |
| 9 | // tidy-alphabetical-end |
| 10 | |
| 11 | use proc_macro::TokenStream; |
| 12 | use synstructure::decl_derive; |
| 13 | |
| 14 | mod current_version; |
| 15 | mod diagnostics; |
| 16 | mod extension; |
| 17 | mod hash_stable; |
| 18 | mod lift; |
| 19 | mod print_attribute; |
| 20 | mod query; |
| 21 | mod serialize; |
| 22 | mod symbols; |
| 23 | mod try_from; |
| 24 | mod type_foldable; |
| 25 | mod type_visitable; |
| 26 | |
| 27 | // Reads the rust version (e.g. "1.75.0") from the CFG_RELEASE env var and |
| 28 | // produces a `RustcVersion` literal containing that version (e.g. |
| 29 | // `RustcVersion { major: 1, minor: 75, patch: 0 }`). |
| 30 | #[proc_macro ] |
| 31 | pub fn current_rustc_version(input: TokenStream) -> TokenStream { |
| 32 | current_version::current_version(input) |
| 33 | } |
| 34 | |
| 35 | #[proc_macro ] |
| 36 | pub fn rustc_queries(input: TokenStream) -> TokenStream { |
| 37 | query::rustc_queries(input) |
| 38 | } |
| 39 | |
| 40 | #[proc_macro ] |
| 41 | pub fn symbols(input: TokenStream) -> TokenStream { |
| 42 | symbols::symbols(input.into()).into() |
| 43 | } |
| 44 | |
| 45 | /// Derive an extension trait for a given impl block. The trait name |
| 46 | /// goes into the parenthesized args of the macro, for greppability. |
| 47 | /// For example: |
| 48 | /// ``` |
| 49 | /// use rustc_macros::extension; |
| 50 | /// #[extension(pub trait Foo)] |
| 51 | /// impl i32 { fn hello() {} } |
| 52 | /// ``` |
| 53 | /// |
| 54 | /// expands to: |
| 55 | /// ``` |
| 56 | /// pub trait Foo { fn hello(); } |
| 57 | /// impl Foo for i32 { fn hello() {} } |
| 58 | /// ``` |
| 59 | #[proc_macro_attribute ] |
| 60 | pub fn extension (attr: TokenStream, input: TokenStream) -> TokenStream { |
| 61 | extension::extension(attr, input) |
| 62 | } |
| 63 | |
| 64 | decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive); |
| 65 | decl_derive!( |
| 66 | [HashStable_Generic, attributes(stable_hasher)] => |
| 67 | hash_stable::hash_stable_generic_derive |
| 68 | ); |
| 69 | decl_derive!( |
| 70 | [HashStable_NoContext] => |
| 71 | /// `HashStable` implementation that has no `HashStableContext` bound and |
| 72 | /// which adds `where` bounds for `HashStable` based off of fields and not |
| 73 | /// generics. This is suitable for use in crates like `rustc_type_ir`. |
| 74 | hash_stable::hash_stable_no_context_derive |
| 75 | ); |
| 76 | |
| 77 | decl_derive!([Decodable_NoContext] => serialize::decodable_nocontext_derive); |
| 78 | decl_derive!([Encodable_NoContext] => serialize::encodable_nocontext_derive); |
| 79 | decl_derive!([Decodable] => serialize::decodable_derive); |
| 80 | decl_derive!([Encodable] => serialize::encodable_derive); |
| 81 | decl_derive!([TyDecodable] => serialize::type_decodable_derive); |
| 82 | decl_derive!([TyEncodable] => serialize::type_encodable_derive); |
| 83 | decl_derive!([MetadataDecodable] => serialize::meta_decodable_derive); |
| 84 | decl_derive!([MetadataEncodable] => serialize::meta_encodable_derive); |
| 85 | decl_derive!( |
| 86 | [TypeFoldable, attributes(type_foldable)] => |
| 87 | /// Derives `TypeFoldable` for the annotated `struct` or `enum` (`union` is not supported). |
| 88 | /// |
| 89 | /// The fold will produce a value of the same struct or enum variant as the input, with |
| 90 | /// each field respectively folded using the `TypeFoldable` implementation for its type. |
| 91 | /// However, if a field of a struct or an enum variant is annotated with |
| 92 | /// `#[type_foldable(identity)]` then that field will retain its incumbent value (and its |
| 93 | /// type is not required to implement `TypeFoldable`). |
| 94 | type_foldable::type_foldable_derive |
| 95 | ); |
| 96 | decl_derive!( |
| 97 | [TypeVisitable, attributes(type_visitable)] => |
| 98 | /// Derives `TypeVisitable` for the annotated `struct` or `enum` (`union` is not supported). |
| 99 | /// |
| 100 | /// Each field of the struct or enum variant will be visited in definition order, using the |
| 101 | /// `TypeVisitable` implementation for its type. However, if a field of a struct or an enum |
| 102 | /// variant is annotated with `#[type_visitable(ignore)]` then that field will not be |
| 103 | /// visited (and its type is not required to implement `TypeVisitable`). |
| 104 | type_visitable::type_visitable_derive |
| 105 | ); |
| 106 | decl_derive!([Lift, attributes(lift)] => lift::lift_derive); |
| 107 | decl_derive!( |
| 108 | [Diagnostic, attributes( |
| 109 | // struct attributes |
| 110 | diag, |
| 111 | help, |
| 112 | help_once, |
| 113 | note, |
| 114 | note_once, |
| 115 | warning, |
| 116 | // field attributes |
| 117 | skip_arg, |
| 118 | primary_span, |
| 119 | label, |
| 120 | subdiagnostic, |
| 121 | suggestion, |
| 122 | suggestion_short, |
| 123 | suggestion_hidden, |
| 124 | suggestion_verbose)] => diagnostics::diagnostic_derive |
| 125 | ); |
| 126 | decl_derive!( |
| 127 | [LintDiagnostic, attributes( |
| 128 | // struct attributes |
| 129 | diag, |
| 130 | help, |
| 131 | help_once, |
| 132 | note, |
| 133 | note_once, |
| 134 | warning, |
| 135 | // field attributes |
| 136 | skip_arg, |
| 137 | primary_span, |
| 138 | label, |
| 139 | subdiagnostic, |
| 140 | suggestion, |
| 141 | suggestion_short, |
| 142 | suggestion_hidden, |
| 143 | suggestion_verbose)] => diagnostics::lint_diagnostic_derive |
| 144 | ); |
| 145 | decl_derive!( |
| 146 | [Subdiagnostic, attributes( |
| 147 | // struct/variant attributes |
| 148 | label, |
| 149 | help, |
| 150 | help_once, |
| 151 | note, |
| 152 | note_once, |
| 153 | warning, |
| 154 | subdiagnostic, |
| 155 | suggestion, |
| 156 | suggestion_short, |
| 157 | suggestion_hidden, |
| 158 | suggestion_verbose, |
| 159 | multipart_suggestion, |
| 160 | multipart_suggestion_short, |
| 161 | multipart_suggestion_hidden, |
| 162 | multipart_suggestion_verbose, |
| 163 | // field attributes |
| 164 | skip_arg, |
| 165 | primary_span, |
| 166 | suggestion_part, |
| 167 | applicability)] => diagnostics::subdiagnostic_derive |
| 168 | ); |
| 169 | |
| 170 | decl_derive! { |
| 171 | [TryFromU32] => |
| 172 | /// Derives `TryFrom<u32>` for the annotated `enum`, which must have no fields. |
| 173 | /// Each variant maps to the value it would produce under an `as u32` cast. |
| 174 | /// |
| 175 | /// The error type is `u32`. |
| 176 | try_from::try_from_u32 |
| 177 | } |
| 178 | decl_derive! { |
| 179 | [PrintAttribute] => |
| 180 | /// Derives `PrintAttribute` for `AttributeKind`. |
| 181 | /// This macro is pretty specific to `rustc_attr_data_structures` and likely not that useful in |
| 182 | /// other places. It's deriving something close to `Debug` without printing some extraenous |
| 183 | /// things like spans. |
| 184 | print_attribute::print_attribute |
| 185 | } |
| 186 | |