dtolnay / quote

Rust quasi-quoting
Apache License 2.0
1.32k stars 90 forks source link

Can one rely on `ToTokens` not being implemented for `proc_macro::TokenStream` #265

Closed ModProg closed 1 year ago

ModProg commented 1 year ago

I created a macro that allows proc macro implementations to accept both proc_macro2::TokenStream and proc_macro::TokenStream.

I recently got a request to also accept impl Parse and output impl ToTokens.

This would mean that I couldn't support accepting/returning proc_macro::TokenStream anymore, as it doesn't implement ToTokens/Parse. Which would make e.g. parse_macro_input or similar tools unusable.

In case it is safe to assume that proc_macro::TokenStream will not implement these traits, it would be possible to support both proc_macro::TokenStream and impl ToTokens, even without specialization, by having two separate traits with conflicting function names.

dtolnay commented 1 year ago

Use https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md and then you won't need this assumption.

ModProg commented 1 year ago

I thought about it some more, and I think it is actually not possible to implement this with autoref, because autoref only works on functions that take a value, but (and this is not quote but syn) Parse wouldn't take the value it would return it.

I'll just drop support for proc_macro::TokenStream and syn::parse_macro_input, as it is probably sensible to use proc_macro2 for most cases anyway.

dtolnay commented 1 year ago

You can turn any function that doesn't take a value into a function that takes a value.

struct WhatType<T>(PhantomData<T>);

impl<T> WhatType<T> {
    fn foo(&self) -> T {
        T::whatever()
    }
}

WhatType(PhantomData::<T>).foo()