ACP: add proc_macro::ToTokens to support proc_macro::quote · Issue #431 · rust-lang/libs-team (original) (raw)

Proposal

Problem statement

Context: rust-lang/rust#54722 (comment)

Our version of quote! currently relies on From<TokenStream>, which has some limitations:

These are pretty notable limitations compared to quote::quote!, for which all of the above work.

Motivating examples or use cases

The following does not work:

let x = pm::Ident::new("foo", pm::Span::call_site()); let _ = pm::quote! { // ERROR: From<proc_macro::Ident> is not implemented for proc_macro::TokenStream let $x = 199; };

Reusing the same item is inconvenient:

let x1: pm::TokenStream = pm::Ident::new("foo", pm::Span::call_site()).into(); let x2 = x1.clone(); let _ = pm::quote! { let mut $x1 = 199; $x2 += 10; };

Solution sketch

  1. Add proc_macro::ToTokens that is identical to quote::ToTokens:
    pub trait ToTokens {
    fn to_tokens(&self, tokens: &mut TokenStream);
    fn to_token_stream(&self) -> TokenStream { ... }
    fn into_token_stream(self) -> TokenStream
    where Self: Sized { ... }

} 2. Implement this for most types that have quote::ToTokens, including:

  1. Change pm::quote to make use of ToTokens when it expands, rather than From
  2. Reimplement some TokenStream conversion traits in terms of ToTokens if this can be done without breakage
    // currently Extend<TokenStream> and Extend<TokenTree>
    impl Extend<T: ToTokens> for TokenStream { /* ... / }
    // currently FromIterator<TokenStream> and FromIterator<TokenTree>
    impl FromIterator<T: ToTokens> for TokenStream { /
    ... */ }
    This does some of the job quote::TokenStreamExt.

Alternatives

What happens now?

This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.

Possible responses

The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):

Second, if there's a concrete solution: