Skip to content

Env vars set by proc macros should be cleared after a macro expansion #11355

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

Closed
vlad20012 opened this issue Jan 27, 2022 · 4 comments · Fixed by #11356
Closed

Env vars set by proc macros should be cleared after a macro expansion #11355

vlad20012 opened this issue Jan 27, 2022 · 4 comments · Fixed by #11356

Comments

@vlad20012
Copy link
Member

vlad20012 commented Jan 27, 2022

Some macros change their environment variables. For example, sqlx loads all variables from .env file. These envs can affect the expansion of other macros. For example, an sqlx macro from crate A can affect sqlx macros from crate B.

Demo:

#[proc_macro]
pub fn set_var(_: TokenStream) -> TokenStream {
    std::env::set_var("FOO", "bad");
    TokenStream::new()
}

#[proc_macro]
pub fn read_var(_: TokenStream) -> TokenStream {
    let var = std::env::var("FOO").unwrap_or_else(|_| "good".to_string());
    format!("\"{}\"", var).parse().unwrap()
}

then use them like this:

fn main() {
    my_proc_macro::set_var!();
    let b = my_proc_macro::read_var!();
}

read_var!() should be expanded to "good", but it will likely be expanded to "bad".

@bjorn3
Copy link
Member

bjorn3 commented Jan 27, 2022

I think sqlx should be changed to read .env without changing the environment. The env vars will affect other proc macros in the same rustc invocation too. In addition it will break the env var change tracking of rustc/cargo.

@vlad20012
Copy link
Member Author

vlad20012 commented Jan 27, 2022

Yes, I agree. But also, I think that the expander should be resilient to such an abusing

@bjorn3
Copy link
Member

bjorn3 commented Jan 27, 2022

Rustc isn't robust against it either.

@vlad20012
Copy link
Member Author

vlad20012 commented Jan 28, 2022

Rustc is a bit more robust. Since a new rustc process is created for each crate, these env vars are not shared between crates.
I'm sorry that my example did not show this. We just need to put set_var! and read_var! into different crates.
A real-world example - consider a crate A that uses sqlx and has .env with SQLX_OFFLINE=true, and a crate B that uses sqlx and does not have .env. Then, when compiled by rustc, sqlx macros in crate B assume that SQL_OFFLINE=false since it does not exist. But when expanded by RA, envs from crate A can be shared with macros in crate B, hence the behavior of sqlx macros may differ

@bors bors bot closed this as completed in 6010431 Jan 30, 2022
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

Successfully merging a pull request may close this issue.

2 participants