@@ -4,7 +4,7 @@ use rustc_abi::{BackendRepr, Size, TagEncoding, Variants, WrappingRange};
4
4
use rustc_hir:: { Expr , ExprKind , HirId , LangItem } ;
5
5
use rustc_middle:: bug;
6
6
use rustc_middle:: ty:: layout:: { LayoutOf , SizeSkeleton } ;
7
- use rustc_middle:: ty:: { self , AdtKind , Const , ScalarInt , Ty , TyCtxt , TypeVisitableExt } ;
7
+ use rustc_middle:: ty:: { self , Const , ScalarInt , Ty , TyCtxt , TypeVisitableExt } ;
8
8
use rustc_session:: { declare_lint, declare_lint_pass, impl_lint_pass} ;
9
9
use rustc_span:: { Span , Symbol , sym} ;
10
10
use tracing:: debug;
@@ -868,14 +868,13 @@ fn is_niche_optimization_candidate<'tcx>(
868
868
}
869
869
870
870
/// Check if this enum can be safely exported based on the "nullable pointer optimization". If it
871
- /// can, return the type that `ty` can be safely converted to/from , otherwise return `None`.
871
+ /// can, return the type that `ty` can be safely converted to, otherwise return `None`.
872
872
/// Currently restricted to function pointers, boxes, references, `core::num::NonZero`,
873
873
/// `core::ptr::NonNull`, `#[repr(transparent)]` newtypes, and int-range pattern types.
874
874
pub ( crate ) fn repr_nullable_ptr < ' tcx > (
875
875
tcx : TyCtxt < ' tcx > ,
876
876
typing_env : ty:: TypingEnv < ' tcx > ,
877
877
ty : Ty < ' tcx > ,
878
- checked_conversion_is_from : bool ,
879
878
) -> Option < Ty < ' tcx > > {
880
879
debug ! ( "is_repr_nullable_ptr(tcx, ty = {:?})" , ty) ;
881
880
match ty. kind ( ) {
@@ -901,17 +900,11 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
901
900
} ;
902
901
903
902
if let ty:: Pat ( base, pat) = field_ty. kind ( ) {
904
- return if let Some ( disallowed) = get_pat_disallowed_value_count ( * pat) {
905
- if disallowed != 1 && checked_conversion_is_from {
906
- // if there are values not taken into account by the optionlike Enum
907
- // then we can't safely convert from the base type, only the pattern type
908
- Some ( field_ty)
909
- } else {
910
- get_nullable_type_from_pat ( tcx, typing_env, * base, * pat)
911
- }
903
+ if pattern_has_disallowed_values ( * pat) || matches ! ( base. kind( ) , ty:: Char ) {
904
+ return get_nullable_type_from_pat ( tcx, typing_env, * base, * pat) ;
912
905
} else {
913
- None
914
- } ;
906
+ return None ;
907
+ }
915
908
}
916
909
917
910
if !ty_is_known_nonnull ( tcx, typing_env, field_ty) {
@@ -950,22 +943,13 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
950
943
}
951
944
None
952
945
}
953
- ty:: Pat ( base, pat) => {
954
- if checked_conversion_is_from && get_pat_disallowed_value_count ( * pat) . is_some ( ) {
955
- // if there are values not taken into account by the pattern (the usual case)
956
- // then we can't safely convert from the base type
957
- None
958
- } else {
959
- get_nullable_type_from_pat ( tcx, typing_env, * base, * pat)
960
- }
961
- }
946
+ ty:: Pat ( base, pat) => get_nullable_type_from_pat ( tcx, typing_env, * base, * pat) ,
962
947
_ => None ,
963
948
}
964
949
}
965
950
966
- /// return the number of disallowed values in a pattern type
967
- /// note that Some(0) actually maps to 2^128 rather than 0
968
- pub ( crate ) fn get_pat_disallowed_value_count < ' tcx > ( pat : ty:: Pattern < ' tcx > ) -> Option < u128 > {
951
+ /// returns whether a pattern type actually has disallowed values
952
+ pub ( crate ) fn pattern_has_disallowed_values < ' tcx > ( pat : ty:: Pattern < ' tcx > ) -> bool {
969
953
// note the logic in this function assumes that signed ints use one's complement representation,
970
954
// which I believe is a requirement for rust
971
955
@@ -1028,17 +1012,7 @@ pub(crate) fn get_pat_disallowed_value_count<'tcx>(pat: ty::Pattern<'tcx>) -> Op
1028
1012
( 0 , scalar_size. unsigned_int_max ( ) )
1029
1013
} ;
1030
1014
1031
- if ( start. to_bits ( scalar_size) , end. to_bits ( scalar_size) ) == ( scalar_min, scalar_max) {
1032
- return None ;
1033
- }
1034
-
1035
- // note: allow overflow here because negative values are allowed in the scalars represented here
1036
- let allowed_value_count_minus1 =
1037
- u128:: overflowing_sub ( end. to_bits ( scalar_size) , start. to_bits ( scalar_size) ) . 0
1038
- & scalar_size. unsigned_int_max ( ) ;
1039
- let disallowed_value_count =
1040
- u128:: overflowing_sub ( scalar_size. unsigned_int_max ( ) , allowed_value_count_minus1) . 0 ;
1041
- Some ( disallowed_value_count)
1015
+ ( start. to_bits ( scalar_size) , end. to_bits ( scalar_size) ) != ( scalar_min, scalar_max)
1042
1016
}
1043
1017
ty:: PatternKind :: Or ( patterns) => {
1044
1018
// first, get a simplified an sorted view of the ranges
@@ -1077,8 +1051,6 @@ pub(crate) fn get_pat_disallowed_value_count<'tcx>(pat: ty::Pattern<'tcx>) -> Op
1077
1051
// (`prev_tail` is the highest value currently accounted for by the ranges,
1078
1052
// unless the first range has not been dealt with yet)
1079
1053
let mut prev_tail = scalar_max;
1080
- let mut disallowed_value_count = 0_u128 ;
1081
- let mut only_had_overlaps = true ;
1082
1054
1083
1055
for ( range_i, ( start, end) ) in ranges. into_iter ( ) . enumerate ( ) {
1084
1056
let ( start, end) = ( start. to_bits ( scalar_size) , end. to_bits ( scalar_size) ) ;
@@ -1109,28 +1081,11 @@ pub(crate) fn get_pat_disallowed_value_count<'tcx>(pat: ty::Pattern<'tcx>) -> Op
1109
1081
prev_tail = u128:: max ( prev_tail, end)
1110
1082
}
1111
1083
} else {
1112
- // no range overlap: first, add the newfound disallowed values to the count
1113
- only_had_overlaps = false ;
1114
- let new_gap = u128:: overflowing_sub (
1115
- start,
1116
- u128:: overflowing_add ( prev_tail, 1 ) . 0 & scalar_size. unsigned_int_max ( ) ,
1117
- )
1118
- . 0 & scalar_size. unsigned_int_max ( ) ;
1119
- disallowed_value_count =
1120
- u128:: overflowing_add ( disallowed_value_count, new_gap) . 0 ;
1121
- prev_tail = end;
1084
+ // no range overlap: there are disallowed values
1085
+ return true ;
1122
1086
}
1123
1087
}
1124
- if prev_tail != scalar_max {
1125
- disallowed_value_count = u128:: overflowing_add (
1126
- disallowed_value_count,
1127
- u128:: overflowing_sub ( scalar_max, prev_tail) . 0 ,
1128
- )
1129
- . 0 ;
1130
- only_had_overlaps = false ;
1131
- }
1132
-
1133
- if only_had_overlaps { None } else { Some ( disallowed_value_count) }
1088
+ prev_tail != scalar_max
1134
1089
}
1135
1090
}
1136
1091
}
@@ -1153,38 +1108,6 @@ fn get_nullable_type_from_pat<'tcx>(
1153
1108
}
1154
1109
}
1155
1110
1156
- /// determines wether or not `outer_ty` is an option-like enum, with the same size as its contained type, `ty`.
1157
- /// this ASSUMES that `ty` is a type that is already 'inside' of `outer_ty`.
1158
- fn is_outer_optionlike_around_ty < ' tcx > (
1159
- cx : & LateContext < ' tcx > ,
1160
- outer_ty : Ty < ' tcx > ,
1161
- ty : Ty < ' tcx > ,
1162
- ) -> bool {
1163
- // three things to check to be sure outer_ty is option-like (since we know we reached the current ty from there)
1164
- // That outer_ty is an enum, that this enum doesn't have a defined discriminant representation,
1165
- // and the the outer_ty's size is that of ty.
1166
- if let ty:: Adt ( def, _) = outer_ty. kind ( ) {
1167
- if ( !matches ! ( def. adt_kind( ) , AdtKind :: Enum ) )
1168
- || def. repr ( ) . c ( )
1169
- || def. repr ( ) . transparent ( )
1170
- || def. repr ( ) . int . is_some ( )
1171
- {
1172
- false
1173
- } else {
1174
- let ( tcx, typing_env) = ( cx. tcx , cx. typing_env ( ) ) ;
1175
-
1176
- // see the insides of super::repr_nullable_ptr()
1177
- let compute_size_skeleton = |t| SizeSkeleton :: compute ( t, tcx, typing_env) ;
1178
- match ( compute_size_skeleton ( ty) , compute_size_skeleton ( outer_ty) ) {
1179
- ( Ok ( sk1) , Ok ( sk2) ) => sk1. same_size ( sk2) ,
1180
- _ => false ,
1181
- }
1182
- }
1183
- } else {
1184
- false
1185
- }
1186
- }
1187
-
1188
1111
declare_lint_pass ! ( VariantSizeDifferences => [ VARIANT_SIZE_DIFFERENCES ] ) ;
1189
1112
1190
1113
impl < ' tcx > LateLintPass < ' tcx > for VariantSizeDifferences {
0 commit comments