1
+ use rustc_data_structures:: fx:: FxHashMap ;
1
2
use rustc_hir:: lang_items:: LangItem ;
2
3
use rustc_middle:: mir:: interpret:: { AllocRange , Allocation , ConstAllocation , Scalar as MirScalar } ;
3
4
use rustc_middle:: ty:: layout:: LayoutCx ;
@@ -7,7 +8,7 @@ use rustc_target::abi::{
7
8
Abi , FieldsShape , HasDataLayout , Integer , Primitive , Scalar , Size , TyAndLayout , WrappingRange ,
8
9
} ;
9
10
10
- #[ derive( Debug , Clone , Copy ) ]
11
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
11
12
enum InvariantSize {
12
13
U8 ,
13
14
U16 ,
@@ -17,16 +18,14 @@ enum InvariantSize {
17
18
Pointer ,
18
19
}
19
20
20
- #[ derive( Debug , Clone , Copy ) ]
21
- struct Invariant {
21
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
22
+ struct InvariantKey {
22
23
offset : Size ,
23
24
size : InvariantSize ,
24
- valid_range_start : u128 ,
25
- valid_range_end : u128 ,
26
25
}
27
26
28
27
// FIXME: Don't add duplicate invariants (maybe use a HashMap?)
29
- fn add_invariants < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > , invs : & mut Vec < Invariant > , offset : Size ) {
28
+ fn add_invariants < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > , invs : & mut FxHashMap < InvariantKey , WrappingRange > , offset : Size ) {
30
29
let x = tcx. layout_of ( ParamEnvAnd { param_env : ParamEnv :: reveal_all ( ) , value : ty } ) ;
31
30
32
31
if let Ok ( layout) = x {
@@ -41,8 +40,10 @@ fn add_invariants<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, invs: &mut Vec<Invarian
41
40
Primitive :: F64 => InvariantSize :: U64 ,
42
41
Primitive :: Pointer => InvariantSize :: Pointer ,
43
42
} ;
44
- let WrappingRange { start, end } = valid_range;
45
- invs. push ( Invariant { offset, size, valid_range_start : start, valid_range_end : end } )
43
+
44
+ // Pick the first scalar we see, this means NonZeroU8(u8) ends up with only one
45
+ // invariant, the stricter one.
46
+ let _: Result < _ , _ > = invs. try_insert ( InvariantKey { offset, size } , valid_range) ;
46
47
}
47
48
48
49
let param_env = ParamEnv :: reveal_all ( ) ;
@@ -90,7 +91,7 @@ pub(crate) fn alloc_validity_invariants_of<'tcx>(
90
91
tcx : TyCtxt < ' tcx > ,
91
92
ty : Ty < ' tcx > ,
92
93
) -> ConstAllocation < ' tcx > {
93
- let mut invs: Vec < Invariant > = Vec :: new ( ) ;
94
+ let mut invs = FxHashMap :: default ( ) ;
94
95
95
96
let layout = tcx. data_layout ( ) ;
96
97
let validity_invariant = get_layout_of_invariant ( tcx) ;
@@ -114,21 +115,21 @@ pub(crate) fn alloc_validity_invariants_of<'tcx>(
114
115
. write_scalar (
115
116
& tcx,
116
117
offset_range,
117
- MirScalar :: from_machine_usize ( invariant. offset . bytes ( ) , & tcx) . into ( ) ,
118
+ MirScalar :: from_machine_usize ( invariant. 0 . offset . bytes ( ) , & tcx) . into ( ) ,
118
119
)
119
120
. unwrap ( ) ;
120
121
121
122
let size_range = AllocRange { start : offset + size_off, size : Size :: from_bytes ( 1 ) } ;
122
123
alloc
123
- . write_scalar ( & tcx, size_range, MirScalar :: from_u8 ( invariant. size as u8 ) . into ( ) )
124
+ . write_scalar ( & tcx, size_range, MirScalar :: from_u8 ( invariant. 0 . size as u8 ) . into ( ) )
124
125
. unwrap ( ) ;
125
126
126
127
let offset_range = AllocRange { start : offset + start_off, size : Size :: from_bytes ( 16 ) } ;
127
128
alloc
128
129
. write_scalar (
129
130
& tcx,
130
131
offset_range,
131
- MirScalar :: from_u128 ( invariant. valid_range_start ) . into ( ) ,
132
+ MirScalar :: from_u128 ( invariant. 1 . start ) . into ( ) ,
132
133
)
133
134
. unwrap ( ) ;
134
135
@@ -137,7 +138,7 @@ pub(crate) fn alloc_validity_invariants_of<'tcx>(
137
138
. write_scalar (
138
139
& tcx,
139
140
offset_range,
140
- MirScalar :: from_u128 ( invariant. valid_range_end ) . into ( ) ,
141
+ MirScalar :: from_u128 ( invariant. 1 . end ) . into ( ) ,
141
142
)
142
143
. unwrap ( ) ;
143
144
}
0 commit comments