rust-proc-macros

How can I create hygienic identifiers in code generated by procedural macros?

谁都会走 提交于 2020-01-13 09:25:12
问题 When writing a declarative ( macro_rules! ) macro, we automatically get macro hygiene . In this example, I declare a variable named f in the macro and pass in an identifier f which becomes a local variable: macro_rules! decl_example { ($tname:ident, $mname:ident, ($($fstr:tt),*)) => { impl std::fmt::Display for $tname { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { $mname } = self; write!(f, $($fstr),*) } } } } struct Foo { f: String, } decl_example!(Foo, f,

How do I create a proc_macro_attribute?

坚强是说给别人听的谎言 提交于 2020-01-11 07:13:21
问题 Now that proc_macros have been stabilized, how does one create such a thing? From what I've seen, there's the option of putting a #[proc_macro_attribute] annotation on a fn whatsitsname(attrs: TokenStream, code: TokenStream) -> TokenStream , but how can I register it? How can I add custom attributes? 回答1: The Rust compiler has a fairly complete test suite. When looking for examples of newly-introduced features, I frequently start there: $ rg -c proc_macro_attribute src/test/run-pass-fulldeps

How do I create a proc_macro_attribute?

南笙酒味 提交于 2020-01-11 07:13:07
问题 Now that proc_macros have been stabilized, how does one create such a thing? From what I've seen, there's the option of putting a #[proc_macro_attribute] annotation on a fn whatsitsname(attrs: TokenStream, code: TokenStream) -> TokenStream , but how can I register it? How can I add custom attributes? 回答1: The Rust compiler has a fairly complete test suite. When looking for examples of newly-introduced features, I frequently start there: $ rg -c proc_macro_attribute src/test/run-pass-fulldeps

How can the compilation properties be determined in a procedural macro?

瘦欲@ 提交于 2020-01-03 18:56:15
问题 I'm working on a procedural macro that does a lot of work that can slow down compilation considerably. The work done does not effect the semantics of the function; that is, if given the same set of arguments, the returned value is does not change depending on whether the macro is applied. In an effort to make the edit-comp-test loop quicker, I would like to make the macro a no-op depending on conditions that relate to how the crate is being compiled. I would like to be able to determine two

How to programmatically get the number of fields of a struct?

天涯浪子 提交于 2019-12-30 03:44:48
问题 I have a custom struct like the following: struct MyStruct { first_field: i32, second_field: String, third_field: u16, } Is it possible to get the number of struct fields programmatically (like, for example, via a method call field_count() ): let my_struct = MyStruct::new(10, "second_field", 4); let field_count = my_struct.field_count(); // Expecting to get 3 For this struct: struct MyStruct2 { first_field: i32, } ... the following call should return 1 : let my_struct_2 = MyStruct2::new(7);

Is it possible to store state within Rust's procedural macros?

喜夏-厌秋 提交于 2019-12-20 01:09:03
问题 Is it possible to build a macro that doesn't output anything but instead stores state to build up a list and then a second macro that will then actually use that data? For example: trait SomeTrait {} #[derive(mark)] struct Person {} impl SomeTrait for Person {} #[derive(mark)] struct Item {} impl SomeTrait for Item {} #[derive(mark)] struct Object {} impl SomeTrait for Object {} create_mapper! // this then outputs the below function //assuming for the fact that data is loaded correctly before

What is a suitable place to store procedural macro artifacts so that they are cleaned up by `cargo clean`?

久未见 提交于 2019-12-10 14:54:41
问题 I'm working on a procedural macro that needs a place to store state on the system where it is run. The state should be cleaned up when cargo clean is run. In the past, I've assumed that the target directory is the proper place. However, my assumption is likely incorrect because: my files and directories may conflict with those of rustc and cargo . the location of the target directory can change from the default. In an effort to avoid these issues, I've been attempting to determine a way to

How to report errors in a procedural macro using the quote macro?

丶灬走出姿态 提交于 2019-12-08 15:52:18
问题 I am writing a procedural macro which works fine, but I am having trouble reporting errors in an ergonomic way. Using panic! "works" but is not elegant and does not present the error message to the user nicely. I know that I can report good errors while parsing a TokenStream , but I need to produce errors while traversing the AST after it has been parsed. The macro invocation looks like this: attr_test! { #[bool] FOO } And should output: const FOO: bool = false; This is the macro code: extern

What is this strange syntax where an enum variant is used as a function?

*爱你&永不变心* 提交于 2019-12-01 21:24:57
Below is the example given by the mod documentation of syn::parse . enum Item { Struct(ItemStruct), Enum(ItemEnum), } struct ItemStruct { struct_token: Token![struct], ident: Ident, brace_token: token::Brace, fields: Punctuated<Field, Token![,]>, } impl Parse for Item { fn parse(input: ParseStream) -> Result<Self> { let lookahead = input.lookahead1(); if lookahead.peek(Token![struct]) { input.parse().map(Item::Struct) // <-- here } else if lookahead.peek(Token![enum]) { input.parse().map(Item::Enum) // <-- and here } else { Err(lookahead.error()) } } } Is input.parse().map(Item::Struct) a

Is it possible to store state within Rust's procedural macros?

▼魔方 西西 提交于 2019-12-01 19:35:18
Is it possible to build a macro that doesn't output anything but instead stores state to build up a list and then a second macro that will then actually use that data? For example: trait SomeTrait {} #[derive(mark)] struct Person {} impl SomeTrait for Person {} #[derive(mark)] struct Item {} impl SomeTrait for Item {} #[derive(mark)] struct Object {} impl SomeTrait for Object {} create_mapper! // this then outputs the below function //assuming for the fact that data is loaded correctly before this macro is used fn select_item(kind: String) -> impl SomeTrait { match kind { "person" => Person,