Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect compiler hint for complicated type handler #64548

Open
olegnn opened this issue Sep 17, 2019 · 2 comments

Comments

@olegnn
Copy link

commented Sep 17, 2019

I was trying to implement custom macro parser but fall into strange issue.
Having following code

use proc_macro2::TokenStream;
use quote::quote;
use syn::parse::{Parse, ParseStream, Peek};
use syn::token::Token;

#[derive(Debug)]
struct ParseType {
    pub tokens: TokenStream,
}

mod custom {
    syn::custom_punctuation!(Arrow, ==>);
}

fn parse_until<T: Token>(
    input: ParseStream,
    ending_tokens: &[&impl Peek<Token = T>],
) -> syn::Result<TokenStream> {
    let mut tokens = TokenStream::new();
    while !input.is_empty() && !ending_tokens.into_iter().any(|token| input.peek(token)) {
        let next: proc_macro2::TokenTree = input.parse()?;
        tokens.extend(Some(next));
    }
    Ok(tokens)
}

impl Parse for ParseType {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        Ok(ParseType {
            tokens: parse_until(input, &[&custom::Arrow])?,
        })
    }
}

fn main() {
    let result: syn::Result<ParseType> =
        syn::parse2(quote! { { Ok::<usize, usize>(1) } ==> to the moon });
    println!("Parsed: {:?}", result.unwrap());
}

(Playground)

I got an error

error[E0277]: expected a `std::ops::Fn<(syn::lookahead::TokenMarker,)>` closure, found `impl Peek<Token = T>`
  --> src/main.rs:20:77
   |
20 |     while !input.is_empty() && !ending_tokens.into_iter().any(|token| input.peek(token)) {
   |                                                                             ^^^^ expected an `Fn<(syn::lookahead::TokenMarker,)>` closure, found `impl Peek<Token = T>`
   |
   = help: the trait `std::ops::Fn<(syn::lookahead::TokenMarker,)>` is not implemented for `impl Peek<Token = T>`
   = help: consider adding a `where impl Peek<Token = T>: std::ops::Fn<(syn::lookahead::TokenMarker,)>` bound
   = note: required because of the requirements on the impl of `std::ops::FnOnce<(syn::lookahead::TokenMarker,)>` for `&impl Peek<Token = T>`
   = note: required because of the requirements on the impl of `syn::lookahead::Peek` for `&&impl Peek<Token = T>`

So I added where impl Peek<Token = T>: std::ops::Fn<(syn::lookahead::TokenMarker,)> to the code and then situation became worse:

error[E0603]: module `lookahead` is private
  --> src/main.rs:18:78
   |
18 | ) -> syn::Result<TokenStream> where impl Peek<Token = T>: std::ops::Fn<(syn::lookahead::TokenMarker,)> {
   |                                                                              ^^^^^^^^^

error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
  --> src/main.rs:18:37
   |
18 | ) -> syn::Result<TokenStream> where impl Peek<Token = T>: std::ops::Fn<(syn::lookahead::TokenMarker,)> {
   |                                     ^^^^^^^^^^^^^^^^^^^^

error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead
  --> src/main.rs:18:59
   |
18 | ) -> syn::Result<TokenStream> where impl Peek<Token = T>: std::ops::Fn<(syn::lookahead::TokenMarker,)> {
   |                                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: for more information, see https://github.com/rust-lang/rust/issues/29625

For the first of them it's ok [for me at least] that compiler can't understand which module is private, however the second and the third make me very confused, because this's the code generated by compiler itself.

@olegnn

This comment has been minimized.

Copy link
Author

commented Sep 17, 2019

input.peek(**token)

solved the problem but compiler hints in this case only made this little problem look so terrifying.

@cuviper

This comment has been minimized.

Copy link
Member

commented Sep 21, 2019

#64565 offers a more succinct version of that hint, suggesting where impl Trait bounds that aren't actually valid to write. But any hint along those lines would still be misleading in your case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.