Skip to content

Commit 377086e

Browse files
committed
add freeze_struct_ignore_ra
1 parent ad39bdd commit 377086e

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

support/macros/build.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use std::env;
2+
3+
fn main() {
4+
// Read the RUSTC_WRAPPER environment variable
5+
if let Ok(rustc_wrapper) = env::var("RUSTC_WRAPPER") {
6+
// Pass the RUSTC_WRAPPER to rust build
7+
println!("cargo:rustc-env=RUSTC_WRAPPER={}", rustc_wrapper);
8+
}
9+
}

support/macros/src/lib.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,24 @@ use syn::{parse2, visit_mut::visit_item_struct_mut, Error, ItemStruct, LitStr, R
66
mod visitor;
77
use visitor::*;
88

9+
/// Freezes the layout of a struct to the current hash of its fields, ensuring that future
10+
/// changes require updating the hash.
11+
///
12+
/// If you ever get in a loop where rust analyzer insists that the hash is wrong each time you
13+
/// update, but `cargo check` is passing, you should use [`freeze_struct_ignore_ra`] instead.
914
#[proc_macro_attribute]
1015
pub fn freeze_struct(attr: TokenStream, tokens: TokenStream) -> TokenStream {
11-
match freeze_struct_impl(attr, tokens) {
16+
match freeze_struct_impl(attr, tokens, false) {
17+
Ok(item_struct) => item_struct.to_token_stream().into(),
18+
Err(err) => err.to_compile_error().into(),
19+
}
20+
}
21+
22+
/// More permissive version of [`freeze_struct`] that ignores the hash check when running in
23+
/// rust-analyzer since in some rare situations rust-analyzer will generate an incorrect hash code
24+
#[proc_macro_attribute]
25+
pub fn freeze_struct_ignore_ra(attr: TokenStream, tokens: TokenStream) -> TokenStream {
26+
match freeze_struct_impl(attr, tokens, true) {
1227
Ok(item_struct) => item_struct.to_token_stream().into(),
1328
Err(err) => err.to_compile_error().into(),
1429
}
@@ -17,6 +32,7 @@ pub fn freeze_struct(attr: TokenStream, tokens: TokenStream) -> TokenStream {
1732
fn freeze_struct_impl(
1833
attr: impl Into<TokenStream2>,
1934
tokens: impl Into<TokenStream2>,
35+
ignore_ra: bool,
2036
) -> Result<ItemStruct> {
2137
let attr = attr.into();
2238
let tokens = tokens.into();
@@ -39,6 +55,10 @@ fn freeze_struct_impl(
3955
let mut visitor = CleanDocComments::new();
4056
visit_item_struct_mut(&mut visitor, &mut item_clone);
4157

58+
if ignore_ra && is_rust_analyzer() {
59+
return Ok(item);
60+
}
61+
4262
if provided_hash_hex != calculated_hash_hex {
4363
return Err(Error::new_spanned(item,
4464
format!(
@@ -52,3 +72,10 @@ fn freeze_struct_impl(
5272
}
5373
Ok(item)
5474
}
75+
76+
/// Returns true if the current build is being run by rust-analyzer.
77+
fn is_rust_analyzer() -> bool {
78+
std::env::var("RUSTC_WRAPPER")
79+
.map(|v| v.contains("rust-analyzer"))
80+
.unwrap_or(false)
81+
}

0 commit comments

Comments
 (0)