rust/compiler/rustc_macros/src/lib.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

186 lines
5.8 KiB
Rust
Raw Normal View History

// tidy-alphabetical-start
#![allow(rustc::default_hash_types)]
2022-11-13 13:10:36 +01:00
#![feature(if_let_guard)]
2023-01-09 00:00:41 +01:00
#![feature(let_chains)]
#![feature(never_type)]
#![feature(proc_macro_diagnostic)]
macros: introduce `fluent_messages` macro Adds a new `fluent_messages` macro which performs compile-time validation of the compiler's Fluent resources (i.e. that the resources parse and don't multiply define the same messages) and generates constants that make using those messages in diagnostics more ergonomic. For example, given the following invocation of the macro.. ```ignore (rust) fluent_messages! { typeck => "./typeck.ftl", } ``` ..where `typeck.ftl` has the following contents.. ```fluent typeck-field-multiply-specified-in-initializer = field `{$ident}` specified more than once .label = used more than once .label-previous-use = first use of `{$ident}` ``` ...then the macro parse the Fluent resource, emitting a diagnostic if it fails to do so, and will generate the following code: ```ignore (rust) pub static DEFAULT_LOCALE_RESOURCES: &'static [&'static str] = &[ include_str!("./typeck.ftl"), ]; mod fluent_generated { mod typeck { pub const field_multiply_specified_in_initializer: DiagnosticMessage = DiagnosticMessage::fluent("typeck-field-multiply-specified-in-initializer"); pub const field_multiply_specified_in_initializer_label_previous_use: DiagnosticMessage = DiagnosticMessage::fluent_attr( "typeck-field-multiply-specified-in-initializer", "previous-use-label" ); } } ``` When emitting a diagnostic, the generated constants can be used as follows: ```ignore (rust) let mut err = sess.struct_span_err( span, fluent::typeck::field_multiply_specified_in_initializer ); err.span_default_label(span); err.span_label( previous_use_span, fluent::typeck::field_multiply_specified_in_initializer_label_previous_use ); err.emit(); ``` Signed-off-by: David Wood <david.wood@huawei.com>
2022-05-23 18:24:55 +01:00
#![feature(proc_macro_span)]
#![feature(proc_macro_tracked_env)]
// tidy-alphabetical-end
2019-04-05 13:11:44 +02:00
2018-12-03 01:14:35 +01:00
use proc_macro::TokenStream;
2019-03-05 19:27:50 +01:00
use synstructure::decl_derive;
2018-12-03 01:14:35 +01:00
2023-10-26 17:18:21 -07:00
mod current_version;
mod diagnostics;
2024-02-13 23:49:28 +00:00
mod extension;
2018-12-03 01:14:35 +01:00
mod hash_stable;
mod lift;
2025-02-09 22:50:03 +01:00
mod print_attribute;
2018-12-03 01:14:35 +01:00
mod query;
mod serialize;
mod symbols;
mod try_from;
2019-11-13 20:47:41 +01:00
mod type_foldable;
2022-06-17 10:53:29 +01:00
mod type_visitable;
2018-12-03 01:14:35 +01:00
// Reads the rust version (e.g. "1.75.0") from the CFG_RELEASE env var and
// produces a `RustcVersion` literal containing that version (e.g.
// `RustcVersion { major: 1, minor: 75, patch: 0 }`).
2023-10-26 17:18:21 -07:00
#[proc_macro]
pub fn current_rustc_version(input: TokenStream) -> TokenStream {
current_version::current_version(input)
}
2018-12-03 01:14:35 +01:00
#[proc_macro]
pub fn rustc_queries(input: TokenStream) -> TokenStream {
query::rustc_queries(input)
}
2018-12-03 01:14:35 +01:00
#[proc_macro]
pub fn symbols(input: TokenStream) -> TokenStream {
symbols::symbols(input.into()).into()
}
2024-02-19 16:07:39 +00:00
/// Derive an extension trait for a given impl block. The trait name
/// goes into the parenthesized args of the macro, for greppability.
/// For example:
/// ```
/// use rustc_macros::extension;
/// #[extension(pub trait Foo)]
/// impl i32 { fn hello() {} }
/// ```
///
/// expands to:
/// ```
/// pub trait Foo { fn hello(); }
/// impl Foo for i32 { fn hello() {} }
/// ```
2024-02-13 23:49:28 +00:00
#[proc_macro_attribute]
2024-02-14 17:18:56 +00:00
pub fn extension(attr: TokenStream, input: TokenStream) -> TokenStream {
extension::extension(attr, input)
2024-02-13 23:49:28 +00:00
}
2018-12-16 04:44:12 +01:00
decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
2019-11-09 20:34:55 +01:00
decl_derive!(
[HashStable_Generic, attributes(stable_hasher)] =>
hash_stable::hash_stable_generic_derive
);
decl_derive!(
[HashStable_NoContext] =>
/// `HashStable` implementation that has no `HashStableContext` bound and
/// which adds `where` bounds for `HashStable` based off of fields and not
/// generics. This is suitable for use in crates like `rustc_type_ir`.
hash_stable::hash_stable_no_context_derive
);
2019-11-09 20:34:55 +01:00
decl_derive!([Decodable_NoContext] => serialize::decodable_nocontext_derive);
decl_derive!([Encodable_NoContext] => serialize::encodable_nocontext_derive);
decl_derive!([Decodable] => serialize::decodable_derive);
decl_derive!([Encodable] => serialize::encodable_derive);
decl_derive!([TyDecodable] => serialize::type_decodable_derive);
decl_derive!([TyEncodable] => serialize::type_encodable_derive);
decl_derive!([MetadataDecodable] => serialize::meta_decodable_derive);
decl_derive!([MetadataEncodable] => serialize::meta_encodable_derive);
decl_derive!(
[TypeFoldable, attributes(type_foldable)] =>
/// Derives `TypeFoldable` for the annotated `struct` or `enum` (`union` is not supported).
///
/// The fold will produce a value of the same struct or enum variant as the input, with
/// each field respectively folded using the `TypeFoldable` implementation for its type.
/// However, if a field of a struct or an enum variant is annotated with
/// `#[type_foldable(identity)]` then that field will retain its incumbent value (and its
/// type is not required to implement `TypeFoldable`).
type_foldable::type_foldable_derive
);
decl_derive!(
[TypeVisitable, attributes(type_visitable)] =>
/// Derives `TypeVisitable` for the annotated `struct` or `enum` (`union` is not supported).
///
/// Each field of the struct or enum variant will be visited in definition order, using the
/// `TypeVisitable` implementation for its type. However, if a field of a struct or an enum
/// variant is annotated with `#[type_visitable(ignore)]` then that field will not be
/// visited (and its type is not required to implement `TypeVisitable`).
type_visitable::type_visitable_derive
);
decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
decl_derive!(
[Diagnostic, attributes(
// struct attributes
diag,
help,
help_once,
note,
note_once,
warning,
// field attributes
skip_arg,
primary_span,
label,
subdiagnostic,
suggestion,
suggestion_short,
suggestion_hidden,
suggestion_verbose)] => diagnostics::diagnostic_derive
);
decl_derive!(
[LintDiagnostic, attributes(
// struct attributes
diag,
help,
help_once,
note,
note_once,
warning,
// field attributes
skip_arg,
primary_span,
label,
subdiagnostic,
suggestion,
suggestion_short,
suggestion_hidden,
suggestion_verbose)] => diagnostics::lint_diagnostic_derive
);
decl_derive!(
[Subdiagnostic, attributes(
// struct/variant attributes
label,
help,
help_once,
note,
note_once,
warning,
2024-04-20 12:52:05 +00:00
subdiagnostic,
suggestion,
suggestion_short,
suggestion_hidden,
suggestion_verbose,
multipart_suggestion,
multipart_suggestion_short,
multipart_suggestion_hidden,
multipart_suggestion_verbose,
// field attributes
skip_arg,
primary_span,
suggestion_part,
applicability)] => diagnostics::subdiagnostic_derive
);
decl_derive! {
[TryFromU32] =>
/// Derives `TryFrom<u32>` for the annotated `enum`, which must have no fields.
/// Each variant maps to the value it would produce under an `as u32` cast.
///
/// The error type is `u32`.
try_from::try_from_u32
}
2025-02-09 22:50:03 +01:00
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
}