@@ -118,7 +118,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
118
118
struct ConstPropMachine ;
119
119
120
120
impl < ' mir , ' tcx > interpret:: Machine < ' mir , ' tcx > for ConstPropMachine {
121
- type MemoryKinds = !;
121
+ type MemoryKinds = !;
122
122
type PointerTag = ( ) ;
123
123
type ExtraFnVal = !;
124
124
@@ -460,79 +460,80 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
460
460
let span = source_info. span ;
461
461
462
462
// perform any special checking for specific Rvalue types
463
- if let Rvalue :: UnaryOp ( op, arg) = rvalue {
464
- trace ! ( "checking UnaryOp(op = {:?}, arg = {:?})" , op, arg) ;
465
- let overflow_check = self . tcx . sess . overflow_checks ( ) ;
466
-
467
- self . use_ecx ( source_info, |this| {
468
- // We check overflow in debug mode already
469
- // so should only check in release mode.
470
- if * op == UnOp :: Neg && !overflow_check {
471
- let ty = arg. ty ( & this. local_decls , this. tcx ) ;
472
-
473
- if ty. is_integral ( ) {
474
- let arg = this. ecx . eval_operand ( arg, None ) ?;
475
- let prim = this. ecx . read_immediate ( arg) ?;
476
- // Need to do overflow check here: For actual CTFE, MIR
477
- // generation emits code that does this before calling the op.
478
- if prim. to_bits ( ) ? == ( 1 << ( prim. layout . size . bits ( ) - 1 ) ) {
479
- throw_panic ! ( OverflowNeg )
463
+ match rvalue {
464
+ Rvalue :: UnaryOp ( UnOp :: Neg , arg) => {
465
+ trace ! ( "checking UnaryOp(op = Neg, arg = {:?})" , arg) ;
466
+ let overflow_check = self . tcx . sess . overflow_checks ( ) ;
467
+
468
+ self . use_ecx ( source_info, |this| {
469
+ // We check overflow in debug mode already
470
+ // so should only check in release mode.
471
+ if !overflow_check {
472
+ let ty = arg. ty ( & this. local_decls , this. tcx ) ;
473
+
474
+ if ty. is_integral ( ) {
475
+ let arg = this. ecx . eval_operand ( arg, None ) ?;
476
+ let prim = this. ecx . read_immediate ( arg) ?;
477
+ // Need to do overflow check here: For actual CTFE, MIR
478
+ // generation emits code that does this before calling the op.
479
+ if prim. to_bits ( ) ? == ( 1 << ( prim. layout . size . bits ( ) - 1 ) ) {
480
+ throw_panic ! ( OverflowNeg )
481
+ }
480
482
}
481
483
}
482
- }
483
484
484
- Ok ( ( ) )
485
- } ) ?;
486
- } else if let Rvalue :: BinaryOp ( op, left, right) = rvalue {
487
- trace ! ( "checking BinaryOp(op = {:?}, left = {:?}, right = {:?})" , op, left, right) ;
488
-
489
- let r = self . use_ecx ( source_info, |this| {
490
- this. ecx . read_immediate ( this. ecx . eval_operand ( right, None ) ?)
491
- } ) ?;
492
- if * op == BinOp :: Shr || * op == BinOp :: Shl {
493
- let left_bits = place_layout. size . bits ( ) ;
494
- let right_size = r. layout . size ;
495
- let r_bits = r. to_scalar ( ) . and_then ( |r| r. to_bits ( right_size) ) ;
496
- if r_bits. ok ( ) . map_or ( false , |b| b >= left_bits as u128 ) {
497
- let source_scope_local_data = match self . source_scope_local_data {
498
- ClearCrossCrate :: Set ( ref data) => data,
499
- ClearCrossCrate :: Clear => return None ,
500
- } ;
501
- let dir = if * op == BinOp :: Shr {
502
- "right"
503
- } else {
504
- "left"
505
- } ;
506
- let hir_id = source_scope_local_data[ source_info. scope ] . lint_root ;
507
- self . tcx . lint_hir (
508
- :: rustc:: lint:: builtin:: EXCEEDING_BITSHIFTS ,
509
- hir_id,
510
- span,
511
- & format ! ( "attempt to shift {} with overflow" , dir) ) ;
512
- return None ;
513
- }
485
+ Ok ( ( ) )
486
+ } ) ?;
514
487
}
515
- self . use_ecx ( source_info, |this| {
516
- let l = this. ecx . read_immediate ( this. ecx . eval_operand ( left, None ) ?) ?;
517
- let ( _, overflow, _ty) = this. ecx . overflowing_binary_op ( * op, l, r) ?;
518
-
519
- // We check overflow in debug mode already
520
- // so should only check in release mode.
521
- if !this. tcx . sess . overflow_checks ( ) && overflow {
522
- let err = err_panic ! ( Overflow ( * op) ) . into ( ) ;
523
- return Err ( err) ;
488
+
489
+ Rvalue :: BinaryOp ( op, left, right) => {
490
+ trace ! ( "checking BinaryOp(op = {:?}, left = {:?}, right = {:?})" , op, left, right) ;
491
+
492
+ let r = self . use_ecx ( source_info, |this| {
493
+ this. ecx . read_immediate ( this. ecx . eval_operand ( right, None ) ?)
494
+ } ) ?;
495
+ if * op == BinOp :: Shr || * op == BinOp :: Shl {
496
+ let left_bits = place_layout. size . bits ( ) ;
497
+ let right_size = r. layout . size ;
498
+ let r_bits = r. to_scalar ( ) . and_then ( |r| r. to_bits ( right_size) ) ;
499
+ if r_bits. ok ( ) . map_or ( false , |b| b >= left_bits as u128 ) {
500
+ let source_scope_local_data = match self . source_scope_local_data {
501
+ ClearCrossCrate :: Set ( ref data) => data,
502
+ ClearCrossCrate :: Clear => return None ,
503
+ } ;
504
+ let dir = if * op == BinOp :: Shr {
505
+ "right"
506
+ } else {
507
+ "left"
508
+ } ;
509
+ let hir_id = source_scope_local_data[ source_info. scope ] . lint_root ;
510
+ self . tcx . lint_hir (
511
+ :: rustc:: lint:: builtin:: EXCEEDING_BITSHIFTS ,
512
+ hir_id,
513
+ span,
514
+ & format ! ( "attempt to shift {} with overflow" , dir) ) ;
515
+ return None ;
516
+ }
524
517
}
518
+ self . use_ecx ( source_info, |this| {
519
+ let l = this. ecx . read_immediate ( this. ecx . eval_operand ( left, None ) ?) ?;
520
+ let ( _, overflow, _ty) = this. ecx . overflowing_binary_op ( * op, l, r) ?;
521
+
522
+ // We check overflow in debug mode already
523
+ // so should only check in release mode.
524
+ if !this. tcx . sess . overflow_checks ( ) && overflow {
525
+ let err = err_panic ! ( Overflow ( * op) ) . into ( ) ;
526
+ return Err ( err) ;
527
+ }
525
528
526
- Ok ( ( ) )
527
- } ) ?;
528
- } else if let Rvalue :: Ref ( _, _, place) = rvalue {
529
- trace ! ( "checking Ref({:?})" , place) ;
530
- // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref
531
- // from a function argument that hasn't been assigned to in this function.
532
- if let Place {
533
- base : PlaceBase :: Local ( local) ,
534
- projection : box [ ]
535
- } = place {
529
+ Ok ( ( ) )
530
+ } ) ?;
531
+ }
532
+
533
+ Rvalue :: Ref ( _, _, Place { base : PlaceBase :: Local ( local) , projection : box [ ] } ) => {
534
+ trace ! ( "checking Ref({:?})" , place) ;
535
+ // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref
536
+ // from a function argument that hasn't been assigned to in this function.
536
537
let alive =
537
538
if let LocalValue :: Live ( _) = self . ecx . frame ( ) . locals [ * local] . value {
538
539
true
@@ -543,12 +544,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
543
544
return None ;
544
545
}
545
546
}
546
- } else if let Rvalue :: Aggregate ( _ , operands ) = rvalue {
547
- // FIXME(wesleywiser): const eval will turn this into a `const Scalar(<ZST>)` that
548
- // `SimplifyLocals` doesn't know it can remove.
549
- if operands . len ( ) == 0 {
547
+
548
+ Rvalue :: Aggregate ( _ , operands ) if operands . len ( ) == 0 => {
549
+ // FIXME(wesleywiser): const eval will turn this into a `const Scalar(<ZST>)` that
550
+ // `SimplifyLocals` doesn't know it can remove.
550
551
return None ;
551
552
}
553
+
554
+ _ => { }
552
555
}
553
556
554
557
self . use_ecx ( source_info, |this| {
0 commit comments