@@ -45,6 +45,9 @@ struct UnsafetyVisitor<'a, 'tcx> {
45
45
/// Flag to ensure that we only suggest wrapping the entire function body in
46
46
/// an unsafe block once.
47
47
suggest_unsafe_block : bool ,
48
+ /// Track whether we're currently inside a `&raw const/mut` expression.
49
+ /// Used to allow safe access to union fields when only taking their address.
50
+ in_raw_borrow : bool ,
48
51
}
49
52
50
53
impl < ' tcx > UnsafetyVisitor < ' _ , ' tcx > {
@@ -218,6 +221,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
218
221
inside_adt : false ,
219
222
warnings : self . warnings ,
220
223
suggest_unsafe_block : self . suggest_unsafe_block ,
224
+ in_raw_borrow : false ,
221
225
} ;
222
226
// params in THIR may be unsafe, e.g. a union pattern.
223
227
for param in & inner_thir. params {
@@ -538,14 +542,24 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
538
542
}
539
543
}
540
544
ExprKind :: RawBorrow { arg, .. } => {
545
+ // Set flag when entering raw borrow context
546
+ let old_in_raw_borrow = self . in_raw_borrow ;
547
+ self . in_raw_borrow = true ;
548
+
541
549
if let ExprKind :: Scope { value : arg, .. } = self . thir [ arg] . kind
542
550
&& let ExprKind :: Deref { arg } = self . thir [ arg] . kind
543
551
{
544
552
// Taking a raw ref to a deref place expr is always safe.
545
553
// Make sure the expression we're deref'ing is safe, though.
546
554
visit:: walk_expr ( self , & self . thir [ arg] ) ;
547
- return ;
555
+ } else {
556
+ // Handle other raw borrow cases (including field access)
557
+ visit:: walk_expr ( self , & self . thir [ arg] ) ;
548
558
}
559
+
560
+ // Restore previous state
561
+ self . in_raw_borrow = old_in_raw_borrow;
562
+ return ;
549
563
}
550
564
ExprKind :: Deref { arg } => {
551
565
if let ExprKind :: StaticRef { def_id, .. } | ExprKind :: ThreadLocalRef ( def_id) =
@@ -651,7 +665,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
651
665
"union fields that need dropping should be impossible: {assigned_ty}"
652
666
) ;
653
667
}
654
- } else {
668
+ } else if !self . in_raw_borrow {
669
+ // Union field access is unsafe because the field may be uninitialized.
670
+ // However, `&raw const/mut union.field` is safe since it only computes
671
+ // the field's address without reading the potentially uninitialized value.
655
672
self . requires_unsafe ( expr. span , AccessToUnionField ) ;
656
673
}
657
674
}
@@ -1187,6 +1204,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
1187
1204
inside_adt : false ,
1188
1205
warnings : & mut warnings,
1189
1206
suggest_unsafe_block : true ,
1207
+ in_raw_borrow : false ,
1190
1208
} ;
1191
1209
// params in THIR may be unsafe, e.g. a union pattern.
1192
1210
for param in & thir. params {
0 commit comments