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

Using fn params in generated code #331

Closed
CodeSandwich opened this issue Jan 16, 2018 · 2 comments
Closed

Using fn params in generated code #331

CodeSandwich opened this issue Jan 16, 2018 · 2 comments

Comments

@CodeSandwich
Copy link

CodeSandwich commented Jan 16, 2018

I know it's not a Syn issue, but I have problems with using function parameters in macro-generated code.

I'm writing a procedural macro, which injects some code on the beginning of a function. The code uses function's parameters. Up to now it used Syn 0.11 and after upgrading to 0.12 it still worked fine.

After upgrade I enabled proc-macro2's nightly feature to enable error reporting in code processed by macro. Suddenly all the tests, where injected code used function's parameters started to fail:

error[E0425]: cannot find value `x` in this scope
   --> tests/injecting.rs:641:5
    |
641 |     #[mockable]
    |     ^^^^^^^^^^^ not found in this scope

I tried boiling issue down to minimum example and came up with a primitive macro:

#[proc_macro_attribute]
pub fn print_x(_: TokenStream, token_stream: TokenStream) -> TokenStream {
    println!("BEFORE:\n{}", token_stream);
    let mut tokens: Vec<TokenTree> = token_stream.into_iter().collect();
    tokens.pop();
    tokens.extend(TokenStream::from_str("{println!(\"{}\", x)}").unwrap());
    let new_tokens = tokens.into_iter().collect();
    println!("AFTER:\n{}", new_tokens);
    new_tokens
}

And used it:

#[print_x]
pub fn args_test(x: u32) {
    assert!(x > 1)
}

It failed perfectly:

BEFORE:
pub fn args_test(x: u32) { assert!(x > 1) }
AFTER:
pub fn args_test ( x : u32 ) { println ! ( "{}" , x ) }
error[E0425]: cannot find value `x` in this scope
   --> tests/injecting.rs:662:1
    |
662 | #[print_x]
    | ^^^^^^^^^^ not found in this scope

Manually replacing annotated function with pub fn args_test ( x : u32 ) { println ! ( "{}" , x ) } gives no errors, the code is fine.

The fun escalated when I removed the nightly proc-macro2 feature: real macro started working again, but the boiled-down print_x still failed with the same error.

It's really confusing, I see no logic behind these errors. I know, if it's not a Syn problem, but could anybody help me with it? Thank you!

@dtolnay
Copy link
Owner

dtolnay commented Jan 16, 2018

This has to do with whether the x token is spanned to resolve at the macro call site or at the macro def site. Check out rust-lang/rust#45934 for some background, and see this example of a macro that uses def site and call site spans correctly.

@CodeSandwich
Copy link
Author

You're right, that's exactly my problem, thank you very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants