-
-
Notifications
You must be signed in to change notification settings - Fork 313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support parsing attributes with arbitrary tokens. #111
Conversation
src/attr.rs
Outdated
@@ -170,6 +177,25 @@ pub mod parsing { | |||
) | |||
| | |||
do_parse!( | |||
name_and_token_trees: preceded!( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to implement this here instead of in the meta_item
rule because I needed to use delimited!
to limit how much token_trees
parses. Is there a better way?
Thanks! The implementation looks good but I would prefer an approach more like how it's done in rust-lang/rust#40346/src/libsyntax/ast.rs - Attribute stores tokens instead of a MetaItem. Then we can provide a function to try parsing the tokens as a Metaitem. It seems wrong that if someone's macro expects an attribute to be plain tokens, they would need to handle all four MetaItem cases in case the user's tokens accidentally matched one of the MetaItem patterns. impl Attribute {
fn meta_item(&self) -> Option<MetaItem>;
} Also please update the |
I did think of that but didn't go that way because it would be a bigger breaking change. I can do that if you're okay with it. |
Done, but I want to add more tests for the nested meta items parser as well. |
|
Tests done. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! This looks great. I am busy with some Serde things this week but I scheduled time on Thursday to review more closely and get this published.
Would you be able to also help me with #109? I think that is the only other AST change that needs to happen presently.
src/attr.rs
Outdated
@@ -6,13 +6,97 @@ use std::iter; | |||
#[derive(Debug, Clone, Eq, PartialEq, Hash)] | |||
pub struct Attribute { | |||
pub style: AttrStyle, | |||
pub value: MetaItem, | |||
pub name: Ident, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The one in rustc supports any Path here - for example they have this unit test:
#[::attr_args::identity
fn main() { assert_eq!(foo(), "Hello, world!"); }]
struct Dummy;
Any idea how much harder that would be to support?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I was initially holding off on it to not make a breaking change. But since meta_item()
is already going to be one it makes sense to combine them.
I think I'm done with changes for now. Let me know if you approve so I can squash and fix the first commit's message to mention the other changes since then. |
Hmm something is not right. I tried this code: nothing/src/lib.rsextern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro_derive(Nothing, attributes(inert))]
pub fn demo(input: TokenStream) -> TokenStream {
"".parse().unwrap()
} testing/src/main.rs#![feature(proc_macro)]
#[macro_use]
extern crate nothing;
extern crate syn;
#[derive(Nothing)]
#[inert <T>]
struct S;
fn main() {
let a = "#[inert <T>]";
println!("{:#?}", syn::parse_outer_attr(a).unwrap());
} Using |
You're right. https://github.com/rust-lang/rust/blob/535ee6c7f05e29a6e94edba06b228d64f8ba74ec/src/libsyntax/parse/attr.rs#L152 I'll add |
Ref rust-lang/rust#40346
This is a nightly-only feature (gated by
proc_macro
feature). Maybe you'd prefer it behind a feature instead of enabled by default?