2022-02-09 22:24:51 +00:00
|
|
|
#![feature(allow_internal_unstable)]
|
2022-04-26 10:59:45 +00:00
|
|
|
#![feature(let_else)]
|
2022-05-07 05:02:11 +00:00
|
|
|
#![feature(never_type)]
|
2022-04-26 10:59:45 +00:00
|
|
|
#![feature(proc_macro_diagnostic)]
|
2022-05-23 17:24:55 +00:00
|
|
|
#![feature(proc_macro_span)]
|
2019-08-11 16:55:14 +00:00
|
|
|
#![allow(rustc::default_hash_types)]
|
2022-08-18 18:27:29 +00:00
|
|
|
#![deny(rustc::untranslatable_diagnostic)]
|
|
|
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
2019-12-22 22:42:04 +00:00
|
|
|
#![recursion_limit = "128"]
|
2019-04-05 11:11:44 +00:00
|
|
|
|
2019-03-05 18:27:50 +00:00
|
|
|
use synstructure::decl_derive;
|
2018-12-03 00:14:35 +00:00
|
|
|
|
2018-12-03 00:14:35 +00:00
|
|
|
use proc_macro::TokenStream;
|
|
|
|
|
2022-04-27 01:57:44 +00:00
|
|
|
mod diagnostics;
|
2018-12-03 00:14:35 +00:00
|
|
|
mod hash_stable;
|
2019-11-14 22:31:49 +00:00
|
|
|
mod lift;
|
2022-02-09 22:24:51 +00:00
|
|
|
mod newtype;
|
2018-12-03 00:14:35 +00:00
|
|
|
mod query;
|
2020-06-11 14:49:57 +00:00
|
|
|
mod serialize;
|
2019-04-03 00:43:49 +00:00
|
|
|
mod symbols;
|
2019-12-22 22:42:04 +00:00
|
|
|
mod type_foldable;
|
2022-06-17 09:53:29 +00:00
|
|
|
mod type_visitable;
|
2018-12-03 00:14:35 +00:00
|
|
|
|
|
|
|
#[proc_macro]
|
|
|
|
pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
|
|
|
query::rustc_queries(input)
|
|
|
|
}
|
2018-12-03 00:14:35 +00:00
|
|
|
|
2019-04-03 00:43:49 +00:00
|
|
|
#[proc_macro]
|
|
|
|
pub fn symbols(input: TokenStream) -> TokenStream {
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
symbols::symbols(input.into()).into()
|
2022-02-09 22:24:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates a struct type `S` that can be used as an index with
|
|
|
|
/// `IndexVec` and so on.
|
|
|
|
///
|
|
|
|
/// There are two ways of interacting with these indices:
|
|
|
|
///
|
|
|
|
/// - The `From` impls are the preferred way. So you can do
|
|
|
|
/// `S::from(v)` with a `usize` or `u32`. And you can convert back
|
|
|
|
/// to an integer with `u32::from(s)`.
|
|
|
|
///
|
|
|
|
/// - Alternatively, you can use the methods `S::new(v)` and `s.index()`
|
|
|
|
/// to create/return a value.
|
|
|
|
///
|
|
|
|
/// Internally, the index uses a u32, so the index must not exceed
|
|
|
|
/// `u32::MAX`. You can also customize things like the `Debug` impl,
|
|
|
|
/// what traits are derived, and so forth via the macro.
|
|
|
|
#[proc_macro]
|
|
|
|
#[allow_internal_unstable(step_trait, rustc_attrs, trusted_step)]
|
|
|
|
pub fn newtype_index(input: TokenStream) -> TokenStream {
|
2022-04-13 20:51:34 +00:00
|
|
|
newtype::newtype(input)
|
2019-04-03 00:43:49 +00:00
|
|
|
}
|
|
|
|
|
2022-05-23 17:24:55 +00:00
|
|
|
/// Implements the `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
|
2022-08-10 09:31:10 +00:00
|
|
|
/// typeck_field_multiply_specified_in_initializer =
|
2022-05-23 17:24:55 +00:00
|
|
|
/// field `{$ident}` specified more than once
|
|
|
|
/// .label = used more than once
|
2022-08-10 09:31:10 +00:00
|
|
|
/// .label_previous_use = first use of `{$ident}`
|
2022-05-23 17:24:55 +00:00
|
|
|
/// ```
|
|
|
|
/// ...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 =
|
2022-08-10 09:31:10 +00:00
|
|
|
/// DiagnosticMessage::fluent("typeck_field_multiply_specified_in_initializer");
|
2022-05-23 17:24:55 +00:00
|
|
|
/// pub const field_multiply_specified_in_initializer_label_previous_use: DiagnosticMessage =
|
|
|
|
/// DiagnosticMessage::fluent_attr(
|
2022-08-10 09:31:10 +00:00
|
|
|
/// "typeck_field_multiply_specified_in_initializer",
|
|
|
|
/// "previous_use_label"
|
2022-05-23 17:24:55 +00:00
|
|
|
/// );
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
/// 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();
|
|
|
|
/// ```
|
|
|
|
#[proc_macro]
|
|
|
|
pub fn fluent_messages(input: TokenStream) -> TokenStream {
|
|
|
|
diagnostics::fluent_messages(input)
|
|
|
|
}
|
|
|
|
|
2018-12-16 03:44:12 +00:00
|
|
|
decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
|
2019-11-09 19:34:55 +00:00
|
|
|
decl_derive!(
|
|
|
|
[HashStable_Generic, attributes(stable_hasher)] =>
|
|
|
|
hash_stable::hash_stable_generic_derive
|
|
|
|
);
|
|
|
|
|
2020-06-11 14:49:57 +00:00
|
|
|
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);
|
2019-11-13 19:47:41 +00:00
|
|
|
decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive);
|
2022-06-17 09:53:29 +00:00
|
|
|
decl_derive!([TypeVisitable, attributes(type_visitable)] => type_visitable::type_visitable_derive);
|
2019-11-14 22:31:49 +00:00
|
|
|
decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
|
2020-08-27 10:00:21 +00:00
|
|
|
decl_derive!(
|
|
|
|
[SessionDiagnostic, attributes(
|
2022-03-31 07:35:17 +00:00
|
|
|
// struct attributes
|
|
|
|
warning,
|
2020-08-27 10:00:21 +00:00
|
|
|
error,
|
2022-06-30 07:57:45 +00:00
|
|
|
lint,
|
2022-03-31 11:10:00 +00:00
|
|
|
help,
|
2022-07-11 17:46:24 +00:00
|
|
|
note,
|
|
|
|
warn_,
|
2022-03-31 07:35:17 +00:00
|
|
|
// field attributes
|
2022-03-31 08:02:31 +00:00
|
|
|
skip_arg,
|
2022-03-31 07:50:45 +00:00
|
|
|
primary_span,
|
2020-08-27 10:00:21 +00:00
|
|
|
label,
|
2022-04-27 04:59:48 +00:00
|
|
|
subdiagnostic,
|
2020-08-27 10:00:21 +00:00
|
|
|
suggestion,
|
|
|
|
suggestion_short,
|
|
|
|
suggestion_hidden,
|
2022-04-27 01:57:44 +00:00
|
|
|
suggestion_verbose)] => diagnostics::session_diagnostic_derive
|
2020-08-27 10:00:21 +00:00
|
|
|
);
|
2022-06-30 07:57:45 +00:00
|
|
|
decl_derive!(
|
|
|
|
[LintDiagnostic, attributes(
|
|
|
|
// struct attributes
|
|
|
|
warning,
|
|
|
|
error,
|
|
|
|
lint,
|
|
|
|
help,
|
2022-07-11 17:46:24 +00:00
|
|
|
note,
|
|
|
|
warn_,
|
2022-06-30 07:57:45 +00:00
|
|
|
// field attributes
|
|
|
|
skip_arg,
|
|
|
|
primary_span,
|
|
|
|
label,
|
|
|
|
subdiagnostic,
|
|
|
|
suggestion,
|
|
|
|
suggestion_short,
|
|
|
|
suggestion_hidden,
|
|
|
|
suggestion_verbose)] => diagnostics::lint_diagnostic_derive
|
|
|
|
);
|
2022-04-26 10:59:45 +00:00
|
|
|
decl_derive!(
|
|
|
|
[SessionSubdiagnostic, attributes(
|
|
|
|
// struct/variant attributes
|
|
|
|
label,
|
|
|
|
help,
|
|
|
|
note,
|
2022-07-11 17:46:24 +00:00
|
|
|
warn_,
|
2022-04-26 10:59:45 +00:00
|
|
|
suggestion,
|
|
|
|
suggestion_short,
|
|
|
|
suggestion_hidden,
|
|
|
|
suggestion_verbose,
|
|
|
|
// field attributes
|
|
|
|
skip_arg,
|
|
|
|
primary_span,
|
2022-04-27 01:57:44 +00:00
|
|
|
applicability)] => diagnostics::session_subdiagnostic_derive
|
2022-04-26 10:59:45 +00:00
|
|
|
);
|