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> {
315
315
}
316
316
_ => ( ) ,
317
317
}
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 ;
318
334
}
319
335
Expr :: MethodCall { .. } => {
320
336
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() {
441
441
)
442
442
}
443
443
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
+
444
487
#[ test]
445
488
fn unsafe_expr_as_an_argument_of_a_method_call ( ) {
446
489
check_fix (
Original file line number Diff line number Diff line change 96
96
97
97
< span class ="variable "> u</ span > < span class ="operator "> .</ span > < span class ="field unsafe "> field</ span > < span class ="semicolon "> ;</ span >
98
98
< 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 >
100
100
< span class ="comment "> // this should be safe!</ span >
101
101
< 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 >
102
102
< span class ="comment "> // but not these</ span >
You can’t perform that action at this time.
0 commit comments