@@ -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 > {
@@ -218,6 +221,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
218221 inside_adt : false ,
219222 warnings : self . warnings ,
220223 suggest_unsafe_block : self . suggest_unsafe_block ,
224+ in_raw_borrow : false ,
221225 } ;
222226 // params in THIR may be unsafe, e.g. a union pattern.
223227 for param in & inner_thir. params {
@@ -538,14 +542,24 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
538542 }
539543 }
540544 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+
541549 if let ExprKind :: Scope { value : arg, .. } = self . thir [ arg] . kind
542550 && let ExprKind :: Deref { arg } = self . thir [ arg] . kind
543551 {
544552 // Taking a raw ref to a deref place expr is always safe.
545553 // Make sure the expression we're deref'ing is safe, though.
546554 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] ) ;
548558 }
559+
560+ // Restore previous state
561+ self . in_raw_borrow = old_in_raw_borrow;
562+ return ;
549563 }
550564 ExprKind :: Deref { arg } => {
551565 if let ExprKind :: StaticRef { def_id, .. } | ExprKind :: ThreadLocalRef ( def_id) =
@@ -651,7 +665,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
651665 "union fields that need dropping should be impossible: {assigned_ty}"
652666 ) ;
653667 }
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.
655672 self . requires_unsafe ( expr. span , AccessToUnionField ) ;
656673 }
657674 }
@@ -1187,6 +1204,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
11871204 inside_adt : false ,
11881205 warnings : & mut warnings,
11891206 suggest_unsafe_block : true ,
1207+ in_raw_borrow : false ,
11901208 } ;
11911209 // params in THIR may be unsafe, e.g. a union pattern.
11921210 for param in & thir. params {
0 commit comments