Add support for repetition to `proc_macro::quote`
@moatom is already working on this.
Since Oct 21, 2025.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Part 1: complete in https://github.com/rust-lang/rust/pull/141608
I'm opening a standalone issue to have something with "help wanted" labels in case anyone is interested in picking this up.
Our proc_macro::quote does not support repetition, unlike quote from the quote crate. As mentioned many times on the tracking issue, this is something we should support or at least account for before proc_macro::quote can be stabilized.
This should use the syntax:
proc_macro::quote! {
$( CONTENTS )SEP*
}
Where CONTENTS is the thing to be repeated and SEP is an optional single-character separator. Expansion should work for anything that implements IntoIterator. This matches the quote crate's logic (except quote::quote uses # rather than $).
It's probably easiest to just copy quote's logic here, which uses an extension trait to facilitate this.
quotecrate source repo: https://github.com/dtolnay/quote.- Link to source for our
quotethat needs to be updated: https://github.com/rust-lang/rust/blob/fa58ce343ad498196d799a7381869e79938e952a/library/proc_macro/src/quote.rs - Link to tests that should be updated: https://github.com/rust-lang/rust/blob/c02a4f0852e6665cf3df3867982021383f5615df/tests/ui/proc-macro/quote/auxiliary/basic.rs (plus any new tests in
tests/ui/proc-macro/quotefor things we should reject) - Tracking issue: https://github.com/rust-lang/rust/issues/54722
Part 2: incomplete
From @dtolnay's comment at https://github.com/rust-lang/rust/pull/141608#issuecomment-2978155580, there are some more minor issues to be resolved before stabilization:
#![feature(proc_macro_quote)]
use proc_macro::TokenStream;
macro_rules! decl {
($($iter:tt)*) => {
stringify!($($iter) << *)
};
}
#[proc_macro]
pub fn repro(input: TokenStream) -> TokenStream {
// macro_rules macro
let tokens = decl!(a b c);
eprintln!("{}", tokens);
// quote crate
let input2 = proc_macro2::TokenStream::from(input.clone());
let iter2 = input2.into_iter();
let tokens = quote::quote!(#(#iter2) << *);
eprintln!("{}", tokens);
// libproc_macro
let iter = input.into_iter();
let tokens = proc_macro::quote!($($iter) << *);
eprintln!("{}", tokens);
TokenStream::new()
}
Macro_rules macro: a << b << c
Quote crate: a << b << c
Libproc_macro:
error: proc macro panicked
--> src/lib.rs:25:18
|
25 | let tokens = proc_macro::quote!($($iter) << *);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: message: `$(...)` must be followed by `*` in `quote!`
Another example:
error[E0425]: cannot find value `j` in this scope
--> src/lib.rs:25:47
|
25 | let tokens = proc_macro::quote!($$ j $($$ j $iter)*);
| ^ not found in this scope
The parsing logic will need some more scrutiny in followup PRs before the macro can be stabilized.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.