@@ -15,41 +15,38 @@ pub enum ConstValue<'tcx> {
1515 /// to allow HIR creation to happen for everything before needing to be able to run constant
1616 /// evaluation
1717 Unevaluated ( DefId , & ' tcx Substs < ' tcx > ) ,
18- /// Used only for types with layout::abi::Scalar ABI and ZSTs which use Scalar::undef()
18+ /// Used only for types with layout::abi::Scalar ABI and ZSTs
1919 Scalar ( Scalar ) ,
2020 /// Used only for types with layout::abi::ScalarPair
21- ScalarPair ( Scalar , Scalar ) ,
21+ ///
22+ /// The second field may be undef in case of `Option<usize>::None`
23+ ScalarPair ( Scalar , ScalarMaybeUndef ) ,
2224 /// Used only for the remaining cases. An allocation + offset into the allocation
2325 ByRef ( & ' tcx Allocation , Size ) ,
2426}
2527
2628impl < ' tcx > ConstValue < ' tcx > {
2729 #[ inline]
28- pub fn from_byval_value ( val : Value ) -> Self {
29- match val {
30+ pub fn from_byval_value ( val : Value ) -> EvalResult < ' static , Self > {
31+ Ok ( match val {
3032 Value :: ByRef ( ..) => bug ! ( ) ,
31- Value :: ScalarPair ( a, b) => ConstValue :: ScalarPair ( a, b) ,
32- Value :: Scalar ( val) => ConstValue :: Scalar ( val) ,
33- }
33+ Value :: ScalarPair ( a, b) => ConstValue :: ScalarPair ( a. unwrap_or_err ( ) ? , b) ,
34+ Value :: Scalar ( val) => ConstValue :: Scalar ( val. unwrap_or_err ( ) ? ) ,
35+ } )
3436 }
3537
3638 #[ inline]
3739 pub fn to_byval_value ( & self ) -> Option < Value > {
3840 match * self {
3941 ConstValue :: Unevaluated ( ..) |
4042 ConstValue :: ByRef ( ..) => None ,
41- ConstValue :: ScalarPair ( a, b) => Some ( Value :: ScalarPair ( a, b) ) ,
42- ConstValue :: Scalar ( val) => Some ( Value :: Scalar ( val) ) ,
43+ ConstValue :: ScalarPair ( a, b) => Some ( Value :: ScalarPair ( a. into ( ) , b) ) ,
44+ ConstValue :: Scalar ( val) => Some ( Value :: Scalar ( val. into ( ) ) ) ,
4345 }
4446 }
4547
4648 #[ inline]
47- pub fn from_scalar ( val : Scalar ) -> Self {
48- ConstValue :: Scalar ( val)
49- }
50-
51- #[ inline]
52- pub fn to_scalar ( & self ) -> Option < Scalar > {
49+ pub fn try_to_scalar ( & self ) -> Option < Scalar > {
5350 match * self {
5451 ConstValue :: Unevaluated ( ..) |
5552 ConstValue :: ByRef ( ..) |
@@ -60,12 +57,12 @@ impl<'tcx> ConstValue<'tcx> {
6057
6158 #[ inline]
6259 pub fn to_bits ( & self , size : Size ) -> Option < u128 > {
63- self . to_scalar ( ) ?. to_bits ( size) . ok ( )
60+ self . try_to_scalar ( ) ?. to_bits ( size) . ok ( )
6461 }
6562
6663 #[ inline]
6764 pub fn to_ptr ( & self ) -> Option < Pointer > {
68- self . to_scalar ( ) ?. to_ptr ( ) . ok ( )
65+ self . try_to_scalar ( ) ?. to_ptr ( ) . ok ( )
6966 }
7067}
7168
@@ -81,8 +78,8 @@ impl<'tcx> ConstValue<'tcx> {
8178#[ derive( Clone , Copy , Debug , Eq , PartialEq , Ord , PartialOrd , RustcEncodable , RustcDecodable , Hash ) ]
8279pub enum Value {
8380 ByRef ( Scalar , Align ) ,
84- Scalar ( Scalar ) ,
85- ScalarPair ( Scalar , Scalar ) ,
81+ Scalar ( ScalarMaybeUndef ) ,
82+ ScalarPair ( ScalarMaybeUndef , ScalarMaybeUndef ) ,
8683}
8784
8885impl < ' tcx > ty:: TypeFoldable < ' tcx > for Value {
@@ -98,23 +95,27 @@ impl<'tcx> Scalar {
9895 pub fn ptr_null < C : HasDataLayout > ( cx : C ) -> Self {
9996 Scalar :: Bits {
10097 bits : 0 ,
101- defined : cx. data_layout ( ) . pointer_size . bits ( ) as u8 ,
98+ size : cx. data_layout ( ) . pointer_size . bytes ( ) as u8 ,
10299 }
103100 }
104101
102+ pub fn to_value_with_len < C : HasDataLayout > ( self , len : u64 , cx : C ) -> Value {
103+ ScalarMaybeUndef :: Scalar ( self ) . to_value_with_len ( len, cx)
104+ }
105+
106+ pub fn to_value_with_vtable ( self , vtable : Pointer ) -> Value {
107+ ScalarMaybeUndef :: Scalar ( self ) . to_value_with_vtable ( vtable)
108+ }
109+
105110 pub fn ptr_signed_offset < C : HasDataLayout > ( self , i : i64 , cx : C ) -> EvalResult < ' tcx , Self > {
106111 let layout = cx. data_layout ( ) ;
107112 match self {
108- Scalar :: Bits { bits, defined } => {
109- let pointer_size = layout. pointer_size . bits ( ) as u8 ;
110- if defined < pointer_size {
111- err ! ( ReadUndefBytes )
112- } else {
113- Ok ( Scalar :: Bits {
114- bits : layout. signed_offset ( bits as u64 , i) ? as u128 ,
115- defined : pointer_size,
116- } )
117- }
113+ Scalar :: Bits { bits, size } => {
114+ assert_eq ! ( size as u64 , layout. pointer_size. bytes( ) ) ;
115+ Ok ( Scalar :: Bits {
116+ bits : layout. signed_offset ( bits as u64 , i) ? as u128 ,
117+ size,
118+ } )
118119 }
119120 Scalar :: Ptr ( ptr) => ptr. signed_offset ( i, layout) . map ( Scalar :: Ptr ) ,
120121 }
@@ -123,65 +124,43 @@ impl<'tcx> Scalar {
123124 pub fn ptr_offset < C : HasDataLayout > ( self , i : Size , cx : C ) -> EvalResult < ' tcx , Self > {
124125 let layout = cx. data_layout ( ) ;
125126 match self {
126- Scalar :: Bits { bits, defined } => {
127- let pointer_size = layout. pointer_size . bits ( ) as u8 ;
128- if defined < pointer_size {
129- err ! ( ReadUndefBytes )
130- } else {
131- Ok ( Scalar :: Bits {
132- bits : layout. offset ( bits as u64 , i. bytes ( ) ) ? as u128 ,
133- defined : pointer_size,
134- } )
135- }
127+ Scalar :: Bits { bits, size } => {
128+ assert_eq ! ( size as u64 , layout. pointer_size. bytes( ) ) ;
129+ Ok ( Scalar :: Bits {
130+ bits : layout. offset ( bits as u64 , i. bytes ( ) ) ? as u128 ,
131+ size,
132+ } )
136133 }
137134 Scalar :: Ptr ( ptr) => ptr. offset ( i, layout) . map ( Scalar :: Ptr ) ,
138135 }
139136 }
140137
141- pub fn ptr_wrapping_signed_offset < C : HasDataLayout > ( self , i : i64 , cx : C ) -> EvalResult < ' tcx , Self > {
138+ pub fn ptr_wrapping_signed_offset < C : HasDataLayout > ( self , i : i64 , cx : C ) -> Self {
142139 let layout = cx. data_layout ( ) ;
143140 match self {
144- Scalar :: Bits { bits, defined } => {
145- let pointer_size = layout. pointer_size . bits ( ) as u8 ;
146- if defined < pointer_size {
147- err ! ( ReadUndefBytes )
148- } else {
149- Ok ( Scalar :: Bits {
150- bits : layout. wrapping_signed_offset ( bits as u64 , i) as u128 ,
151- defined : pointer_size,
152- } )
153- }
141+ Scalar :: Bits { bits, size } => {
142+ assert_eq ! ( size as u64 , layout. pointer_size. bytes( ) ) ;
143+ Scalar :: Bits {
144+ bits : layout. wrapping_signed_offset ( bits as u64 , i) as u128 ,
145+ size,
146+ }
154147 }
155- Scalar :: Ptr ( ptr) => Ok ( Scalar :: Ptr ( ptr. wrapping_signed_offset ( i, layout) ) ) ,
148+ Scalar :: Ptr ( ptr) => Scalar :: Ptr ( ptr. wrapping_signed_offset ( i, layout) ) ,
156149 }
157150 }
158151
159- pub fn is_null_ptr < C : HasDataLayout > ( self , cx : C ) -> EvalResult < ' tcx , bool > {
152+ pub fn is_null_ptr < C : HasDataLayout > ( self , cx : C ) -> bool {
160153 match self {
161- Scalar :: Bits {
162- bits, defined,
163- } => if defined < cx. data_layout ( ) . pointer_size . bits ( ) as u8 {
164- err ! ( ReadUndefBytes )
165- } else {
166- Ok ( bits == 0 )
154+ Scalar :: Bits { bits, size } => {
155+ assert_eq ! ( size as u64 , cx. data_layout( ) . pointer_size. bytes( ) ) ;
156+ bits == 0
167157 } ,
168- Scalar :: Ptr ( _) => Ok ( false ) ,
158+ Scalar :: Ptr ( _) => false ,
169159 }
170160 }
171161
172- pub fn to_value_with_len < C : HasDataLayout > ( self , len : u64 , cx : C ) -> Value {
173- Value :: ScalarPair ( self , Scalar :: Bits {
174- bits : len as u128 ,
175- defined : cx. data_layout ( ) . pointer_size . bits ( ) as u8 ,
176- } )
177- }
178-
179- pub fn to_value_with_vtable ( self , vtable : Pointer ) -> Value {
180- Value :: ScalarPair ( self , Scalar :: Ptr ( vtable) )
181- }
182-
183162 pub fn to_value ( self ) -> Value {
184- Value :: Scalar ( self )
163+ Value :: Scalar ( ScalarMaybeUndef :: Scalar ( self ) )
185164 }
186165}
187166
@@ -199,8 +178,9 @@ impl From<Pointer> for Scalar {
199178pub enum Scalar {
200179 /// The raw bytes of a simple value.
201180 Bits {
202- /// The first `defined` number of bits are valid
203- defined : u8 ,
181+ /// The first `size` bytes are the value.
182+ /// Do not try to read less or more bytes that that
183+ size : u8 ,
204184 bits : u128 ,
205185 } ,
206186
@@ -210,25 +190,63 @@ pub enum Scalar {
210190 Ptr ( Pointer ) ,
211191}
212192
213- impl < ' tcx > Scalar {
214- pub fn undef ( ) -> Self {
215- Scalar :: Bits { bits : 0 , defined : 0 }
193+ #[ derive( Clone , Copy , Debug , Eq , PartialEq , Ord , PartialOrd , RustcEncodable , RustcDecodable , Hash ) ]
194+ pub enum ScalarMaybeUndef {
195+ Scalar ( Scalar ) ,
196+ Undef ,
197+ }
198+
199+ impl From < Scalar > for ScalarMaybeUndef {
200+ fn from ( s : Scalar ) -> Self {
201+ ScalarMaybeUndef :: Scalar ( s)
202+ }
203+ }
204+
205+ impl ScalarMaybeUndef {
206+ pub fn unwrap_or_err ( self ) -> EvalResult < ' static , Scalar > {
207+ match self {
208+ ScalarMaybeUndef :: Scalar ( scalar) => Ok ( scalar) ,
209+ ScalarMaybeUndef :: Undef => err ! ( ReadUndefBytes ) ,
210+ }
211+ }
212+
213+ pub fn to_value_with_len < C : HasDataLayout > ( self , len : u64 , cx : C ) -> Value {
214+ Value :: ScalarPair ( self , Scalar :: Bits {
215+ bits : len as u128 ,
216+ size : cx. data_layout ( ) . pointer_size . bytes ( ) as u8 ,
217+ } . into ( ) )
216218 }
217219
220+ pub fn to_value_with_vtable ( self , vtable : Pointer ) -> Value {
221+ Value :: ScalarPair ( self , Scalar :: Ptr ( vtable) . into ( ) )
222+ }
223+
224+ pub fn ptr_offset < C : HasDataLayout > ( self , i : Size , cx : C ) -> EvalResult < ' tcx , Self > {
225+ match self {
226+ ScalarMaybeUndef :: Scalar ( scalar) => {
227+ scalar. ptr_offset ( i, cx) . map ( ScalarMaybeUndef :: Scalar )
228+ } ,
229+ ScalarMaybeUndef :: Undef => Ok ( ScalarMaybeUndef :: Undef )
230+ }
231+ }
232+ }
233+
234+ impl < ' tcx > Scalar {
218235 pub fn from_bool ( b : bool ) -> Self {
219- // FIXME: can we make defined `1`?
220- Scalar :: Bits { bits : b as u128 , defined : 8 }
236+ Scalar :: Bits { bits : b as u128 , size : 1 }
221237 }
222238
223239 pub fn from_char ( c : char ) -> Self {
224- Scalar :: Bits { bits : c as u128 , defined : 32 }
240+ Scalar :: Bits { bits : c as u128 , size : 4 }
225241 }
226242
227- pub fn to_bits ( self , size : Size ) -> EvalResult < ' tcx , u128 > {
243+ pub fn to_bits ( self , target_size : Size ) -> EvalResult < ' tcx , u128 > {
228244 match self {
229- Scalar :: Bits { .. } if size. bits ( ) == 0 => bug ! ( "to_bits cannot be used with zsts" ) ,
230- Scalar :: Bits { bits, defined } if size. bits ( ) <= defined as u64 => Ok ( bits) ,
231- Scalar :: Bits { .. } => err ! ( ReadUndefBytes ) ,
245+ Scalar :: Bits { bits, size } => {
246+ assert_eq ! ( target_size. bytes( ) , size as u64 ) ;
247+ assert_ne ! ( size, 0 , "to_bits cannot be used with zsts" ) ;
248+ Ok ( bits)
249+ }
232250 Scalar :: Ptr ( _) => err ! ( ReadPointerAsBytes ) ,
233251 }
234252 }
@@ -256,8 +274,8 @@ impl<'tcx> Scalar {
256274
257275 pub fn to_bool ( self ) -> EvalResult < ' tcx , bool > {
258276 match self {
259- Scalar :: Bits { bits : 0 , defined : 8 } => Ok ( false ) ,
260- Scalar :: Bits { bits : 1 , defined : 8 } => Ok ( true ) ,
277+ Scalar :: Bits { bits : 0 , size : 1 } => Ok ( false ) ,
278+ Scalar :: Bits { bits : 1 , size : 1 } => Ok ( true ) ,
261279 _ => err ! ( InvalidBool ) ,
262280 }
263281 }
0 commit comments