diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs
index 3f04b72c2fc6..3c78f5ef3870 100644
--- a/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -315,6 +315,22 @@ impl<'db> UnsafeVisitor<'db> {
}
_ => (),
}
+
+ let mut peeled = *expr;
+ while let Expr::Field { expr: lhs, .. } = &self.body[peeled] {
+ if let Some(Either::Left(FieldId { parent: VariantId::UnionId(_), .. })) =
+ self.infer.field_resolution(peeled)
+ {
+ peeled = *lhs;
+ } else {
+ break;
+ }
+ }
+
+ // Walk the peeled expression (the LHS of the union field chain)
+ self.walk_expr(peeled);
+ // Return so we don't recurse directly onto the union field access(es)
+ return;
}
Expr::MethodCall { .. } => {
if let Some((func, _)) = self.infer.method_resolution(current) {
diff --git a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
index 4bb64747f5bb..029ed18a4d39 100644
--- a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
@@ -441,6 +441,49 @@ fn main() {
)
}
+ #[test]
+ fn raw_deref_on_union_field() {
+ check_diagnostics(
+ r#"
+fn main() {
+
+ union U {
+ a: u8
+ }
+ let x = U { a: 3 };
+
+ let a = &raw mut x.a;
+
+ union U1 {
+ a: u8
+ }
+ let x = U1 { a: 3 };
+
+ let a = x.a;
+ // ^^^ 💡 error: access to union field is unsafe and requires an unsafe function or block
+
+
+ let b = &raw const x.a;
+
+ let tmp = Vec::from([1, 2, 3]);
+
+ let c = &raw const tmp[x.a];
+ // ^^^ 💡 error: access to union field is unsafe and requires an unsafe function or block
+
+ union URef {
+ p: &'static mut i32,
+ }
+
+ fn deref_union_field(u: URef) {
+ // Not an assignment but an access to the union field!
+ *(u.p) = 13;
+ // ^^^ 💡 error: access to union field is unsafe and requires an unsafe function or block
+ }
+}
+"#,
+ )
+ }
+
#[test]
fn unsafe_expr_as_an_argument_of_a_method_call() {
check_fix(
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index 828b8f762c58..8339daf32462 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -96,7 +96,7 @@
u.field;
&u.field;
- &raw const u.field;
+ &raw const u.field;
let Union { field: _ };