@@ -1022,41 +1022,80 @@ where
10221022 let tcx = cx. tcx ( ) ;
10231023 let typing_env = cx. typing_env ( ) ;
10241024
1025+ // Use conservative pointer kind if not optimizing. This saves us the
1026+ // Freeze/Unpin queries, and can save time in the codegen backend (noalias
1027+ // attributes in LLVM have compile-time cost even in unoptimized builds).
1028+ let optimize = tcx. sess . opts . optimize != OptLevel :: No ;
1029+
10251030 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- } )
1031+ ty:: RawPtr ( _, _) | ty:: FnPtr ( ..) if offset. bytes ( ) == 0 => {
1032+ Some ( PointeeInfo { safe : None , size : Size :: ZERO , align : Align :: ONE } )
10321033 }
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 ,
1034+ ty:: Ref ( _, ty, mt) if offset. bytes ( ) == 0 => {
1035+ tcx. layout_of ( typing_env. as_query_input ( ty) ) . ok ( ) . map ( |layout| {
1036+ let ( size, kind) ;
1037+ 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+ kind = 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+ kind = PointerKind :: MutableRef { unpin } ;
1060+ }
1061+ } ;
1062+ PointeeInfo { safe : Some ( kind) , size, align : 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).
1044- 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 {
1065+
1066+ ty:: Adt ( ..)
1067+ if offset. bytes ( ) == 0
1068+ && let Some ( pointee) = this. ty . boxed_ty ( ) =>
1069+ {
1070+ tcx. layout_of ( typing_env. as_query_input ( pointee) ) . ok ( ) . map ( |layout| PointeeInfo {
1071+ safe : Some ( PointerKind :: Box {
1072+ // Same logic as for mutable references above.
10501073 unpin : optimize
1051- && ty. is_unpin ( tcx, typing_env)
1052- && ty. is_unsafe_unpin ( tcx, typing_env) ,
1053- } ,
1054- } ;
1074+ && pointee. is_unpin ( tcx, typing_env)
1075+ && pointee. is_unsafe_unpin ( tcx, typing_env) ,
1076+ global : this. ty . is_box_global ( tcx) ,
1077+ } ) ,
1078+
1079+ // `Box` are not necessarily dereferenceable for the entire duration of the function as
1080+ // they can be deallocated at any time.
1081+ // (if we had "dereferenceable on entry", we could support this)
1082+ size : Size :: ZERO ,
10551083
1056- tcx. layout_of ( typing_env. as_query_input ( ty) ) . ok ( ) . map ( |layout| PointeeInfo {
1057- size : layout. size ,
10581084 align : layout. align . abi ,
1059- safe : Some ( kind) ,
1085+ } )
1086+ }
1087+
1088+ ty:: Adt ( adt_def, ..) if adt_def. is_maybe_dangling ( ) => {
1089+ Self :: ty_and_layout_pointee_info_at ( this. field ( cx, 0 ) , cx, offset) . map ( |info| {
1090+ PointeeInfo {
1091+ // Mark the pointer as raw
1092+ // (thus removing noalias/readonly/etc in case of the llvm backend)
1093+ safe : None ,
1094+ // Make sure we don't assert dereferenceability of the pointer.
1095+ size : Size :: ZERO ,
1096+ // Preserve the alignment assertion! That is required even inside `MaybeDangling`.
1097+ align : info. align ,
1098+ }
10601099 } )
10611100 }
10621101
@@ -1098,7 +1137,7 @@ where
10981137 }
10991138 }
11001139 Variants :: Multiple { .. } => None ,
1101- _ => Some ( this) ,
1140+ Variants :: Empty | Variants :: Single { .. } => Some ( this) ,
11021141 } ;
11031142
11041143 if let Some ( variant) = data_variant
@@ -1135,24 +1174,6 @@ where
11351174 }
11361175 }
11371176
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-
11561177 result
11571178 }
11581179 } ;
0 commit comments