-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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 thread-local state inside proc-macro causes ICE #66003
Comments
Seems to have been fixed, at least, I cannot reproduce. Closing. I don't think a test is needed here. |
@Mark-Simulacrum latest nightly:
Check the repo https://github.com/olegnn/proc-macro-ICE if you can't reproduce on playground. |
I feel like this is intentional behavior, though I guess we probably want to produce an error rather than ICEing. Reopening. |
It's generally hard to handle this gracefully due to how deep it is in the whole system - usually a panic inside a proc macro would turn into an error but here it doesn't seem to. @olegnn This kind of code can't work, every time a proc macro is ran, the It's probably better to replace |
The original purpose of most of this refactoring was actually to cache the generated `TokenStream`s, since constantly regenerating these takes a long time (an extra ~20000ns per call) and these calls happen thousands of times. However, it turns out that: 1. It not valid to retain any TokenStream between different invocations of a proc-macro. Trying will cause the compiler to crash (rust-lang/rust#66003); 2. `syn::Ident` has some problem where it will also cause the compiler to crash if it ends up in thread-local storage (rust-lang/rust#80473) and upstream seems to want to stop any thread-local storage in proc-macros eventually (rust-lang/rust#56058). Being able to cache these tokens would provide a small but decent speedup (~3%), so it is unfortunate that this is not possible. Still, the formatting changes made while trying to implement a cache seem reasonable enough to keep in the tree.
The original purpose of most of this refactoring was actually to cache the generated `TokenStream`s, since constantly regenerating these takes a long time (an extra ~20000ns per call) and these calls happen thousands of times. However, it turns out that: 1. It not valid to retain any TokenStream between different invocations of a proc-macro. Trying will cause the compiler to crash (rust-lang/rust#66003); 2. `syn::Ident` has some problem where it will also cause the compiler to crash if it ends up in thread-local storage (rust-lang/rust#80473) and upstream seems to want to stop any thread-local storage in proc-macros eventually (rust-lang/rust#56058). Being able to cache these tokens would provide a small but decent speedup (~3%), so it is unfortunate that this is not possible. Still, the formatting changes made while trying to implement a cache seem reasonable enough to keep in the tree.
The original purpose of most of this refactoring was actually to cache the generated `TokenStream`s, since constantly regenerating these takes a long time (an extra ~20000ns per call) and these calls happen thousands of times. However, it turns out that: 1. It not valid to retain any TokenStream between different invocations of a proc-macro. Trying will cause the compiler to crash (rust-lang/rust#66003); 2. `syn::Ident` has some problem where it will also cause the compiler to crash if it ends up in thread-local storage (rust-lang/rust#80473) and upstream seems to want to stop any thread-local storage in proc-macros eventually (rust-lang/rust#56058). Being able to cache these tokens would provide a small but decent speedup (~3%), so it is unfortunate that this is not possible. Still, the formatting changes made while trying to implement a cache seem reasonable enough to keep in the tree.
Current output:
|
Hi Thank you for your investigation so far.
If (subsequent) May I guess: The current restriction/ICE is in place to prevent/alert macro developers so as not to make a mess. Could we introduce a configuration option to suppress that check? Yes, if a macro or its output depends on the thread (or the thread ID...), then the macro or its output/tests will break. But that's because such a macro is dirty.
See minimized:
The above unhelpful error message is the same on both |
(Updated): Producing ICE for me, too. |
std::thread::LocalKey
inside proc-macro produces ICE
It just happened for me fn types() -> HashSet<Ident> {
let idents: Punctuated<Ident, Comma> = parse_quote!(Select, End, Receive, Branch);
idents.into_iter().collect()
}
thread_local! {
static TYPES: HashSet<Ident> = types();
}
rustc 1.74.0-nightly (0288f2e 2023-09-25) |
ICE will be produced on any channel.
Error:
LocalKey
used in macro generation:Macro calls (should be 2 at least) which produce error:
Repo with minimal code sample: https://github.com/olegnn/proc-macro-ICE.
The text was updated successfully, but these errors were encountered: