@@ -45,6 +45,9 @@ struct UnsafetyVisitor<'a, 'tcx> {
4545 /// Flag to ensure that we only suggest wrapping the entire function body in
4646 /// an unsafe block once.
4747 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 ,
4851}
4952
5053impl < ' tcx > UnsafetyVisitor < ' _ , ' tcx > {
@@ -223,6 +226,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
223226 inside_adt : false ,
224227 warnings : self . warnings ,
225228 suggest_unsafe_block : self . suggest_unsafe_block ,
229+ in_raw_borrow : false ,
226230 } ;
227231 // params in THIR may be unsafe, e.g. a union pattern.
228232 for param in & inner_thir. params {
@@ -545,14 +549,24 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
545549 }
546550 }
547551 ExprKind :: RawBorrow { arg, .. } => {
552+ // Set flag when entering raw borrow context
553+ let old_in_raw_borrow = self . in_raw_borrow ;
554+ self . in_raw_borrow = true ;
555+
548556 if let ExprKind :: Scope { value : arg, .. } = self . thir [ arg] . kind
549557 && let ExprKind :: Deref { arg } = self . thir [ arg] . kind
550558 {
551559 // Taking a raw ref to a deref place expr is always safe.
552560 // Make sure the expression we're deref'ing is safe, though.
553561 visit:: walk_expr ( self , & self . thir [ arg] ) ;
554- return ;
562+ } else {
563+ // Handle other raw borrow cases (including field access)
564+ visit:: walk_expr ( self , & self . thir [ arg] ) ;
555565 }
566+
567+ // Restore previous state
568+ self . in_raw_borrow = old_in_raw_borrow;
569+ return ;
556570 }
557571 ExprKind :: Deref { arg } => {
558572 if let ExprKind :: StaticRef { def_id, .. } | ExprKind :: ThreadLocalRef ( def_id) =
@@ -658,7 +672,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
658672 "union fields that need dropping should be impossible: {assigned_ty}"
659673 ) ;
660674 }
661- } else {
675+ } else if !self . in_raw_borrow {
676+ // Union field access is unsafe because the field may be uninitialized.
677+ // However, `&raw const/mut union.field` is safe since it only computes
678+ // the field's address without reading the potentially uninitialized value.
662679 self . requires_unsafe ( expr. span , AccessToUnionField ) ;
663680 }
664681 }
@@ -1199,6 +1216,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
11991216 inside_adt : false ,
12001217 warnings : & mut warnings,
12011218 suggest_unsafe_block : true ,
1219+ in_raw_borrow : false ,
12021220 } ;
12031221 // params in THIR may be unsafe, e.g. a union pattern.
12041222 for param in & thir. params {
0 commit comments