File tree Expand file tree Collapse file tree 3 files changed +60
-1
lines changed
ide-diagnostics/src/handlers
ide/src/syntax_highlighting/test_data Expand file tree Collapse file tree 3 files changed +60
-1
lines changed Original file line number Diff line number Diff line change @@ -315,6 +315,22 @@ impl<'db> UnsafeVisitor<'db> {
315315 }
316316 _ => ( ) ,
317317 }
318+
319+ let mut peeled = * expr;
320+ while let Expr :: Field { expr : lhs, .. } = & self . body [ peeled] {
321+ if let Some ( Either :: Left ( FieldId { parent : VariantId :: UnionId ( _) , .. } ) ) =
322+ self . infer . field_resolution ( peeled)
323+ {
324+ peeled = * lhs;
325+ } else {
326+ break ;
327+ }
328+ }
329+
330+ // Walk the peeled expression (the LHS of the union field chain)
331+ self . walk_expr ( peeled) ;
332+ // Return so we don't recurse directly onto the union field access(es)
333+ return ;
318334 }
319335 Expr :: MethodCall { .. } => {
320336 if let Some ( ( func, _) ) = self . infer . method_resolution ( current) {
Original file line number Diff line number Diff line change @@ -441,6 +441,49 @@ fn main() {
441441 )
442442 }
443443
444+ #[ test]
445+ fn raw_deref_on_union_field ( ) {
446+ check_diagnostics (
447+ r#"
448+ fn main() {
449+
450+ union U {
451+ a: u8
452+ }
453+ let x = U { a: 3 };
454+
455+ let a = &raw mut x.a;
456+
457+ union U1 {
458+ a: u8
459+ }
460+ let x = U1 { a: 3 };
461+
462+ let a = x.a;
463+ // ^^^ 💡 error: access to union field is unsafe and requires an unsafe function or block
464+
465+
466+ let b = &raw const x.a;
467+
468+ let tmp = Vec::from([1, 2, 3]);
469+
470+ let c = &raw const tmp[x.a];
471+ // ^^^ 💡 error: access to union field is unsafe and requires an unsafe function or block
472+
473+ union URef {
474+ p: &'static mut i32,
475+ }
476+
477+ fn deref_union_field(u: URef) {
478+ // Not an assignment but an access to the union field!
479+ *(u.p) = 13;
480+ // ^^^ 💡 error: access to union field is unsafe and requires an unsafe function or block
481+ }
482+ }
483+ "# ,
484+ )
485+ }
486+
444487 #[ test]
445488 fn unsafe_expr_as_an_argument_of_a_method_call ( ) {
446489 check_fix (
Original file line number Diff line number Diff line change 9696
9797 < span class ="variable "> u</ span > < span class ="operator "> .</ span > < span class ="field unsafe "> field</ span > < span class ="semicolon "> ;</ span >
9898 < span class ="operator "> &</ span > < span class ="variable "> u</ span > < span class ="operator "> .</ span > < span class ="field unsafe "> field</ span > < span class ="semicolon "> ;</ span >
99- < span class ="operator "> &</ span > < span class ="keyword "> raw</ span > < span class ="keyword const "> const</ span > < span class ="variable "> u</ span > < span class ="operator "> .</ span > < span class ="field unsafe "> field</ span > < span class ="semicolon "> ;</ span >
99+ < span class ="operator "> &</ span > < span class ="keyword "> raw</ span > < span class ="keyword const "> const</ span > < span class ="variable "> u</ span > < span class ="operator "> .</ span > < span class ="field "> field</ span > < span class ="semicolon "> ;</ span >
100100 < span class ="comment "> // this should be safe!</ span >
101101 < span class ="keyword "> let</ span > < span class ="union "> Union</ span > < span class ="brace "> {</ span > < span class ="field "> field</ span > < span class ="colon "> :</ span > < span class ="punctuation "> _</ span > < span class ="brace "> }</ span > < span class ="semicolon "> ;</ span >
102102 < span class ="comment "> // but not these</ span >
You can’t perform that action at this time.
0 commit comments