Skip to content

Add support for repetition to proc_macro::quote #140238

Open
@tgross35

Description

@tgross35

Part 1: complete in #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.

Part 2: incomplete

From @dtolnay's comment at #141608 (comment), 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-proc-macrosArea: Procedural macrosC-feature-requestCategory: A feature request, i.e: not implemented / a PR.E-help-wantedCall for participation: Help is requested to fix this issue.E-mediumCall for participation: Medium difficulty. Experience needed to fix: Intermediate.T-libsRelevant to the library team, which will review and decide on the PR/issue.WG-macrosWorking group: Macros

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions