@@ -429,16 +429,34 @@ pub fn handle_const_operation(
429
429
None
430
430
}
431
431
}
432
- BinaryOp :: BitAnd | BinaryOp :: BitXor | BinaryOp :: BitOr | BinaryOp :: LShift | BinaryOp :: RShift => {
432
+ BinaryOp :: LShift | BinaryOp :: RShift => {
433
+ if let Some ( left_number) = left. as_int ( )
434
+ && let Some ( right_number) = right. as_int ( )
435
+ {
436
+ // only the lower 5 bits are used when shifting, so don't do anything
437
+ // if the shift amount is outside [0,32)
438
+ if ( 0 ..32 ) . contains ( & right_number) {
439
+ res. set_number ( match expr. op {
440
+ BinaryOp :: LShift => left_number << right_number,
441
+ BinaryOp :: RShift => left_number >> right_number,
442
+ _ => unreachable ! ( ) ,
443
+ } as f64 ) ;
444
+ } else {
445
+ res. set_number ( left_number as f64 ) ;
446
+ }
447
+ Some ( res)
448
+ } else {
449
+ None
450
+ }
451
+ }
452
+ BinaryOp :: BitAnd | BinaryOp :: BitXor | BinaryOp :: BitOr => {
433
453
if let Some ( left_number) = left. as_int ( )
434
454
&& let Some ( right_number) = right. as_int ( )
435
455
{
436
456
res. set_number ( match expr. op {
437
457
BinaryOp :: BitAnd => left_number & right_number,
438
458
BinaryOp :: BitXor => left_number ^ right_number,
439
459
BinaryOp :: BitOr => left_number | right_number,
440
- BinaryOp :: LShift => left_number << right_number,
441
- BinaryOp :: RShift => left_number >> right_number,
442
460
_ => unreachable ! ( ) ,
443
461
} as f64 ) ;
444
462
Some ( res)
0 commit comments