@@ -1023,40 +1023,66 @@ where
10231023 let typing_env = cx. typing_env ( ) ;
10241024
10251025 let pointee_info = match * this. ty . kind ( ) {
1026- ty:: RawPtr ( p_ty, _) if offset. bytes ( ) == 0 => {
1027- tcx. layout_of ( typing_env. as_query_input ( p_ty) ) . ok ( ) . map ( |layout| PointeeInfo {
1028- size : layout. size ,
1029- align : layout. align . abi ,
1030- safe : None ,
1031- } )
1026+ ty:: RawPtr ( _, _) | ty:: FnPtr ( ..) if offset. bytes ( ) == 0 => {
1027+ Some ( PointeeInfo { safe : None , size : Size :: ZERO , align : None } )
10321028 }
1033- ty:: FnPtr ( ..) if offset. bytes ( ) == 0 => {
1034- tcx. layout_of ( typing_env. as_query_input ( this. ty ) ) . ok ( ) . map ( |layout| PointeeInfo {
1035- size : layout. size ,
1036- align : layout. align . abi ,
1037- safe : None ,
1029+ ty:: Ref ( _, ty, mt) if offset. bytes ( ) == 0 => {
1030+ tcx. layout_of ( typing_env. as_query_input ( ty) ) . ok ( ) . map ( |layout| {
1031+ // Use conservative pointer kind if not optimizing. This saves us the
1032+ // Freeze/Unpin queries, and can save time in the codegen backend (noalias
1033+ // attributes in LLVM have compile-time cost even in unoptimized builds).
1034+ let optimize = tcx. sess . opts . optimize != OptLevel :: No ;
1035+
1036+ let size;
1037+ let kind = match mt {
1038+ hir:: Mutability :: Not => {
1039+ let frozen = optimize && ty. is_freeze ( tcx, typing_env) ;
1040+
1041+ // Non-frozen shared references are not necessarily dereferenceable for the entire duration of the function
1042+ // (see <https://github.com/rust-lang/rust/pull/98017>)
1043+ // (if we had "dereferenceable on entry", we could support this)
1044+ size = if frozen { layout. size } else { Size :: ZERO } ;
1045+
1046+ PointerKind :: SharedRef { frozen }
1047+ }
1048+ hir:: Mutability :: Mut => {
1049+ let unpin = optimize
1050+ && ty. is_unpin ( tcx, typing_env)
1051+ && ty. is_unsafe_unpin ( tcx, typing_env) ;
1052+
1053+ // Mutable references to potentially self-referential types are not
1054+ // necessarily dereferenceable for the entire duration of the function
1055+ // (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>)
1056+ // (if we had "dereferenceable on entry", we could support this)
1057+ size = if unpin { layout. size } else { Size :: ZERO } ;
1058+
1059+ PointerKind :: MutableRef { unpin }
1060+ }
1061+ } ;
1062+ PointeeInfo { safe : Some ( kind) , size, align : Some ( layout. align . abi ) }
10381063 } )
10391064 }
1040- ty:: Ref ( _, ty, mt) if offset. bytes ( ) == 0 => {
1041- // Use conservative pointer kind if not optimizing. This saves us the
1042- // Freeze/Unpin queries, and can save time in the codegen backend (noalias
1043- // attributes in LLVM have compile-time cost even in unoptimized builds).
1065+
1066+ ty:: Adt ( ..)
1067+ if offset. bytes ( ) == 0
1068+ && let Some ( pointee) = this. ty . boxed_ty ( ) =>
1069+ {
10441070 let optimize = tcx. sess . opts . optimize != OptLevel :: No ;
1045- let kind = match mt {
1046- hir:: Mutability :: Not => {
1047- PointerKind :: SharedRef { frozen : optimize && ty. is_freeze ( tcx, typing_env) }
1048- }
1049- hir:: Mutability :: Mut => PointerKind :: MutableRef {
1071+
1072+ tcx. layout_of ( typing_env. as_query_input ( pointee) ) . ok ( ) . map ( |layout| PointeeInfo {
1073+ safe : Some ( PointerKind :: Box {
10501074 unpin : optimize
1051- && ty . is_unpin ( tcx, typing_env)
1052- && ty . is_unsafe_unpin ( tcx, typing_env) ,
1053- } ,
1054- } ;
1075+ && pointee . is_unpin ( tcx, typing_env)
1076+ && pointee . is_unsafe_unpin ( tcx, typing_env) ,
1077+ global : this . ty . is_box_global ( tcx ) ,
1078+ } ) ,
10551079
1056- tcx. layout_of ( typing_env. as_query_input ( ty) ) . ok ( ) . map ( |layout| PointeeInfo {
1057- size : layout. size ,
1058- align : layout. align . abi ,
1059- safe : Some ( kind) ,
1080+ // `Box` are not necessarily dereferenceable for the entire duration of the function as
1081+ // they can be deallocated at any time.
1082+ // (if we had "dereferenceable on entry", we could support this)
1083+ size : Size :: ZERO ,
1084+
1085+ align : Some ( layout. align . abi ) ,
10601086 } )
10611087 }
10621088
@@ -1098,7 +1124,7 @@ where
10981124 }
10991125 }
11001126 Variants :: Multiple { .. } => None ,
1101- _ => Some ( this) ,
1127+ Variants :: Empty | Variants :: Single { .. } => Some ( this) ,
11021128 } ;
11031129
11041130 if let Some ( variant) = data_variant
@@ -1135,24 +1161,6 @@ where
11351161 }
11361162 }
11371163
1138- // Fixup info for the first field of a `Box`. Recursive traversal will have found
1139- // the raw pointer, so size and align are set to the boxed type, but `pointee.safe`
1140- // will still be `None`.
1141- if let Some ( ref mut pointee) = result {
1142- if offset. bytes ( ) == 0
1143- && let Some ( boxed_ty) = this. ty . boxed_ty ( )
1144- {
1145- debug_assert ! ( pointee. safe. is_none( ) ) ;
1146- let optimize = tcx. sess . opts . optimize != OptLevel :: No ;
1147- pointee. safe = Some ( PointerKind :: Box {
1148- unpin : optimize
1149- && boxed_ty. is_unpin ( tcx, typing_env)
1150- && boxed_ty. is_unsafe_unpin ( tcx, typing_env) ,
1151- global : this. ty . is_box_global ( tcx) ,
1152- } ) ;
1153- }
1154- }
1155-
11561164 result
11571165 }
11581166 } ;
0 commit comments