Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upReview proc macro API 1.2 #50473
Conversation
rust-highfive
assigned
alexcrichton
May 6, 2018
This comment has been minimized.
This comment has been minimized.
|
(rust_highfive has picked a reviewer for you, use r? to override) |
rust-highfive
added
the
S-waiting-on-review
label
May 6, 2018
This comment has been minimized.
This comment has been minimized.
|
@dtolnay @alexcrichton @eddyb @nrc |
petrochenkov
referenced this pull request
May 6, 2018
Closed
Tracking issue for RFC 1566: Procedural macros #38356
This comment has been minimized.
This comment has been minimized.
|
|
eddyb
reviewed
May 6, 2018
| @@ -207,7 +236,7 @@ pub mod token_stream { | |||
|
|
|||
| /// `quote!(..)` accepts arbitrary tokens and expands into a `TokenStream` describing the input. | |||
| /// For example, `quote!(a + b)` will produce a expression, that, when evaluated, constructs | |||
| /// the `TokenStream` `[Word("a"), Op('+', Alone), Word("b")]`. | |||
| /// the `TokenStream` `[Word("a"), Punct('+', Alone), Word("b")]`. | |||
This comment has been minimized.
This comment has been minimized.
eddyb
reviewed
May 6, 2018
| /// An identifier or lifetime identifier. | ||
| Ident(Ident), | ||
| /// A single punctuation character (`+`, `,`, `$`, etc.). | ||
| Punct(Punct), |
This comment has been minimized.
This comment has been minimized.
eddyb
May 6, 2018
Member
Oh I didn't expect these changes. I should leave most of this up to @alexcrichton (I do not have a strong preference either way).
eddyb
reviewed
May 6, 2018
| '^', '&', '|', '@', '.', ',', ';', ':', '#', '$', '?']; | ||
| if !LEGAL_CHARS.contains(&ch) { | ||
| panic!("unsupported character `{:?}`", ch) | ||
| } |
This comment has been minimized.
This comment has been minimized.
eddyb
May 6, 2018
Member
Validation seems really nice, I think previously it's been deferred until conversion to the compiler-internal forms is needed.
eddyb
reviewed
May 6, 2018
| #[derive(Copy, Clone, Debug)] | ||
| #[unstable(feature = "proc_macro", issue = "38356")] | ||
| pub struct Term { | ||
| pub struct Ident { | ||
| // REVIEW(INTERNAL) Symbol + Span is actually `ast::Ident`! We can use it here. |
This comment has been minimized.
This comment has been minimized.
eddyb
reviewed
May 6, 2018
| @@ -1199,7 +1300,7 @@ impl TokenTree { | |||
| '#' => Pound, | |||
| '$' => Dollar, | |||
| '?' => Question, | |||
| _ => panic!("unsupported character {}", op), | |||
| _ => panic!("unsupported character {}", ch), | |||
This comment has been minimized.
This comment has been minimized.
eddyb
May 6, 2018
Member
Can this become unreachable!() now? As only a finite set of characters can be used.
eddyb
reviewed
May 6, 2018
| /// An identifier (`ident`) or lifetime identifier (`'ident`). | ||
| /// | ||
| /// REVIEW ATTENTION: `Copy` impl on a struct with private fields. | ||
| /// REVIEW Do we want to guarantee `Ident` to be `Copy`? |
This comment has been minimized.
This comment has been minimized.
eddyb
May 6, 2018
Member
If we do keep it Copy, that means we can never soundly offer an &self -> &str API. See #38356 (comment).
This comment has been minimized.
This comment has been minimized.
shepmaster
added
S-waiting-on-author
and removed
S-waiting-on-review
labels
May 6, 2018
petrochenkov
changed the title
[WIP] Review proc macro API 1.2
Review proc macro API 1.2
May 7, 2018
petrochenkov
added
S-waiting-on-review
and removed
S-waiting-on-author
labels
May 7, 2018
This comment has been minimized.
This comment has been minimized.
|
All the changes here look great to me, thanks @petrochenkov! While we've already FCP'd for stability in #38356 I think the I'd prefer to land this all at once if possible to reduce churn in the ecosystem, so I'd be mostly in favor of going ahead and stabilizing everything in this PR (if you're ok with that). I don't mind doing the work myself for the APIs here and pushing those up (annotation-wise). Along those lines, want to remove |
alexcrichton
reviewed
May 7, 2018
| /// May fail for a number of reasons, for example, if the string contains unbalanced delimiters | ||
| /// or characters not existing in the language. | ||
| /// | ||
| /// REVIEW The function actually panics on any error and never returns `LexError`. |
This comment has been minimized.
This comment has been minimized.
alexcrichton
May 7, 2018
Member
I think this doesn't match the original implementation, when we first started we were sure to return an error I thought...
In any case I'd think it's a bug that this panics, it should definitely be returning an error (but we can fix that later)
| /// Creates a token stream containing a single token tree. | ||
| /// | ||
| /// REVIEW We don't generally have impls `From<T> for Collection<T>`, but I see why this exists | ||
| /// REVIEW from practical point of view. |
This comment has been minimized.
This comment has been minimized.
alexcrichton
May 7, 2018
Member
Yeah this is currently the main way to go from a TokenTree to a TokenStream, and I think we also accidentally stabilized it already so we're required to keep it.
| @@ -227,6 +256,9 @@ pub fn quote_span(span: Span) -> TokenStream { | |||
| } | |||
|
|
|||
| /// A region of source code, along with macro expansion information. | |||
| /// | |||
| /// REVIEW ATTENTION: `Copy` impl on a struct with private fields. | |||
| /// REVIEW Do we want to guarantee `Span` to be `Copy`? Yes. | |||
This comment has been minimized.
This comment has been minimized.
| TokenTree::Literal(ref tt) => tt.fmt(f), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// REVIEW the impls below are kind of `From<T> for Option<T>`, not strictly necessary, | ||
| /// REVIEW but convenient. No harm, I guess. I'd actually like to see impls | ||
| /// REVIEW `From<Group/Ident/Punct/Literal> for TokenStream` to avoid stuttering like |
This comment has been minimized.
This comment has been minimized.
alexcrichton
May 7, 2018
Member
I suspect impls like these will grow and come to exist over time yeah, that's definitely the direction that libstd has taken.
| /// forms of `Spacing` returned. | ||
| /// | ||
| /// REVIEW ATTENTION: `Copy` impl on a struct with private fields. | ||
| /// REVIEW Do we want to guarantee `Punct` to be `Copy`? |
This comment has been minimized.
This comment has been minimized.
alexcrichton
May 7, 2018
Member
I think this is less critical than Span to be copy, and wouldn't mind going either way here. Making this not-Copy is probably the most conservative thing to do
This comment has been minimized.
This comment has been minimized.
| /// which can be further configured with the `set_span` method below. | ||
| /// | ||
| /// REVIEW Why we even use `char` here? There's no reason to use unicode here. | ||
| /// REVIEW I guess because it's more convenient to write `new('+')` than `new(b'+')`, that's ok. |
This comment has been minimized.
This comment has been minimized.
| /// | ||
| /// REVIEW Again, there's no need for unicode here, | ||
| /// REVIEW except for maybe future compatibility in case Rust turns into APL, | ||
| /// REVIEW but if it's more convenient to use `char` then that's okay. |
This comment has been minimized.
This comment has been minimized.
dtolnay
reviewed
May 7, 2018
|
The reason we decided against TokenTree::Ident was because the matcher |
This comment has been minimized.
This comment has been minimized.
|
@dtolnay The key questions here are probably:
|
This comment has been minimized.
This comment has been minimized.
Sure, I'll add |
This comment has been minimized.
This comment has been minimized.
Probably to parse anything looking like a list of generics, if you want to tell apart |
This comment has been minimized.
This comment has been minimized.
I would need to play with this in nightly before I would feel comfortable committing to it. What I wouldn't want is:
|
This comment has been minimized.
This comment has been minimized.
Hmm, can we imagine any macros that would need to handle lifetime parameters and type parameters differently? There is some appeal in being able to say the distinction never matters until much later in the compile process. |
This comment has been minimized.
This comment has been minimized.
|
One place I can imagine running into trouble is if a macro somehow needs to handle optional lifetimes on a reference. macro_rules! m {
(& $($p:lifetime)? $i:ident) => {}
}
m!(&foo);
m!(&'a foo);
|
This comment has been minimized.
This comment has been minimized.
This is a weird error. I never investigated how our macro matching works in detail, but I expected it to be modeled after regular expressions (greedy by default) and work in both cases, whether extern crate regex;
use regex::Regex;
fn main() {
let not_subset = Regex::new(r"a?b").unwrap();
assert!(not_subset.is_match("ab"));
assert!(not_subset.is_match("b"));
let subset = Regex::new(r"a?\w").unwrap();
assert!(subset.is_match("ab"));
assert!(subset.is_match("aa"));
assert!(subset.is_match("b"));
assert!(subset.is_match("a"));
}http://play.rust-lang.org/?gist=372d5a5f25219670dabc89a1dfb536ba&version=nightly&mode=debug |
This comment has been minimized.
This comment has been minimized.
|
We have 6 weeks if we want to stabilize the API in 1.28. @eddyb
|
petrochenkov
referenced this pull request
May 8, 2018
Merged
stabilize macro_lifetime_matcher #50385
eddyb
added
the
I-nominated
label
May 8, 2018
petrochenkov
added some commits
May 5, 2018
petrochenkov
force-pushed the
petrochenkov:pmapi
branch
from
a2e7f6c
to
dab8c0a
May 15, 2018
petrochenkov
changed the title
Review and stabilize proc macro API 1.2
Review proc macro API 1.2
May 15, 2018
This comment has been minimized.
This comment has been minimized.
|
@bors r=alexcrichton Stabilization commit for later cherry-picking: petrochenkov@3e71e49 |
This comment has been minimized.
This comment has been minimized.
|
|
bors
added
S-waiting-on-bors
and removed
S-waiting-on-author
labels
May 15, 2018
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
bors
added a commit
that referenced
this pull request
May 16, 2018
This comment has been minimized.
This comment has been minimized.
|
|
petrochenkov commentedMay 6, 2018
•
edited
cc #38356
Summary of applied changes:
Term->Ident,TokenTree::Term->TokenTree::Ident,Op->Punct,TokenTree::Op->TokenTree::Punct,Op::op->Punct::as_char.Ident::as_str, useDisplayimpl forIdentinstead.Ident::new_rawfor creating a raw identifier (I'm not surenew_xit's a very idiomatic name though).Punct::newnow ensures that the inputcharis a valid punctuation character in Rust.Ident::newensures that the inputstris a valid identifier in Rust.Punct('\'', Spacing::Joint)andIdent("lifetime_name_without_quote")similarly to multi-character operators.A bit of motivation for renaming (although it was already stated in the review comments):
Identis the single most appropriate name for this thing, especially if we are doing input validation on construction.TokenTree::Identeffectively wrapstoken::Identorast::Ident + is_raw, its meaning is "identifier" and it's already namedidentin declarative macros.Punct, the motivation is thatOpis actively misleading. The thing doesn't mean an operator, it's neither a subset of operators (there is non-operator punctuation in the language), nor superset (operators can be multicharacter while this thing is always a single character). So I named itPunct(first proposed in the original RFC, then by @SimonSapin) , together with input validation it's now a subset of ASCII punctuation character category (u8::is_ascii_punctuation).