1
+ use std:: convert:: TryFrom ;
2
+
1
3
use rustc:: mir;
2
4
use rustc:: mir:: interpret:: { InterpResult , Scalar } ;
3
5
use rustc:: ty:: {
@@ -130,28 +132,27 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
130
132
// Shift ops can have an RHS with a different numeric type.
131
133
if bin_op == Shl || bin_op == Shr {
132
134
let signed = left_layout. abi . is_signed ( ) ;
133
- let mut oflo = ( r as u32 as u128 ) != r;
134
- let mut r = r as u32 ;
135
- let size = left_layout. size ;
136
- oflo |= r >= size. bits ( ) as u32 ;
137
- r %= size. bits ( ) as u32 ;
135
+ let size = u128:: from ( left_layout. size . bits ( ) ) ;
136
+ let overflow = r >= size;
137
+ let r = r % size; // mask to type size
138
+ let r = u32:: try_from ( r) . unwrap ( ) ; // we masked so this will always fit
138
139
let result = if signed {
139
140
let l = self . sign_extend ( l, left_layout) as i128 ;
140
141
let result = match bin_op {
141
- Shl => l << r ,
142
- Shr => l >> r ,
142
+ Shl => l. checked_shl ( r ) . unwrap ( ) ,
143
+ Shr => l. checked_shr ( r ) . unwrap ( ) ,
143
144
_ => bug ! ( "it has already been checked that this is a shift op" ) ,
144
145
} ;
145
146
result as u128
146
147
} else {
147
148
match bin_op {
148
- Shl => l << r ,
149
- Shr => l >> r ,
149
+ Shl => l. checked_shl ( r ) . unwrap ( ) ,
150
+ Shr => l. checked_shr ( r ) . unwrap ( ) ,
150
151
_ => bug ! ( "it has already been checked that this is a shift op" ) ,
151
152
}
152
153
} ;
153
154
let truncated = self . truncate ( result, left_layout) ;
154
- return Ok ( ( Scalar :: from_uint ( truncated, size) , oflo , left_layout. ty ) ) ;
155
+ return Ok ( ( Scalar :: from_uint ( truncated, left_layout . size ) , overflow , left_layout. ty ) ) ;
155
156
}
156
157
157
158
// For the remaining ops, the types must be the same on both sides
@@ -193,7 +194,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
193
194
_ => None ,
194
195
} ;
195
196
if let Some ( op) = op {
196
- let l128 = self . sign_extend ( l, left_layout) as i128 ;
197
197
let r = self . sign_extend ( r, right_layout) as i128 ;
198
198
// We need a special check for overflowing remainder:
199
199
// "int_min % -1" overflows and returns 0, but after casting things to a larger int
@@ -206,8 +206,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
206
206
}
207
207
_ => { }
208
208
}
209
+ let l = self . sign_extend ( l, left_layout) as i128 ;
209
210
210
- let ( result, oflo) = op ( l128 , r) ;
211
+ let ( result, oflo) = op ( l , r) ;
211
212
// This may be out-of-bounds for the result type, so we have to truncate ourselves.
212
213
// If that truncation loses any information, we have an overflow.
213
214
let result = result as u128 ;
0 commit comments