@@ -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
@@ -435,79 +435,80 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
435
435
let span = source_info. span ;
436
436
437
437
// perform any special checking for specific Rvalue types
438
- if let Rvalue :: UnaryOp ( op, arg) = rvalue {
439
- trace ! ( "checking UnaryOp(op = {:?}, arg = {:?})" , op, arg) ;
440
- let overflow_check = self . tcx . sess . overflow_checks ( ) ;
441
-
442
- self . use_ecx ( source_info, |this| {
443
- // We check overflow in debug mode already
444
- // so should only check in release mode.
445
- if * op == UnOp :: Neg && !overflow_check {
446
- let ty = arg. ty ( & this. local_decls , this. tcx ) ;
447
-
448
- if ty. is_integral ( ) {
449
- let arg = this. ecx . eval_operand ( arg, None ) ?;
450
- let prim = this. ecx . read_immediate ( arg) ?;
451
- // Need to do overflow check here: For actual CTFE, MIR
452
- // generation emits code that does this before calling the op.
453
- if prim. to_bits ( ) ? == ( 1 << ( prim. layout . size . bits ( ) - 1 ) ) {
454
- throw_panic ! ( OverflowNeg )
438
+ match rvalue {
439
+ Rvalue :: UnaryOp ( UnOp :: Neg , arg) => {
440
+ trace ! ( "checking UnaryOp(op = Neg, arg = {:?})" , arg) ;
441
+ let overflow_check = self . tcx . sess . overflow_checks ( ) ;
442
+
443
+ self . use_ecx ( source_info, |this| {
444
+ // We check overflow in debug mode already
445
+ // so should only check in release mode.
446
+ if !overflow_check {
447
+ let ty = arg. ty ( & this. local_decls , this. tcx ) ;
448
+
449
+ if ty. is_integral ( ) {
450
+ let arg = this. ecx . eval_operand ( arg, None ) ?;
451
+ let prim = this. ecx . read_immediate ( arg) ?;
452
+ // Need to do overflow check here: For actual CTFE, MIR
453
+ // generation emits code that does this before calling the op.
454
+ if prim. to_bits ( ) ? == ( 1 << ( prim. layout . size . bits ( ) - 1 ) ) {
455
+ throw_panic ! ( OverflowNeg )
456
+ }
455
457
}
456
458
}
457
- }
458
459
459
- Ok ( ( ) )
460
- } ) ?;
461
- } else if let Rvalue :: BinaryOp ( op, left, right) = rvalue {
462
- trace ! ( "checking BinaryOp(op = {:?}, left = {:?}, right = {:?})" , op, left, right) ;
463
-
464
- let r = self . use_ecx ( source_info, |this| {
465
- this. ecx . read_immediate ( this. ecx . eval_operand ( right, None ) ?)
466
- } ) ?;
467
- if * op == BinOp :: Shr || * op == BinOp :: Shl {
468
- let left_bits = place_layout. size . bits ( ) ;
469
- let right_size = r. layout . size ;
470
- let r_bits = r. to_scalar ( ) . and_then ( |r| r. to_bits ( right_size) ) ;
471
- if r_bits. ok ( ) . map_or ( false , |b| b >= left_bits as u128 ) {
472
- let source_scope_local_data = match self . source_scope_local_data {
473
- ClearCrossCrate :: Set ( ref data) => data,
474
- ClearCrossCrate :: Clear => return None ,
475
- } ;
476
- let dir = if * op == BinOp :: Shr {
477
- "right"
478
- } else {
479
- "left"
480
- } ;
481
- let hir_id = source_scope_local_data[ source_info. scope ] . lint_root ;
482
- self . tcx . lint_hir (
483
- :: rustc:: lint:: builtin:: EXCEEDING_BITSHIFTS ,
484
- hir_id,
485
- span,
486
- & format ! ( "attempt to shift {} with overflow" , dir) ) ;
487
- return None ;
488
- }
460
+ Ok ( ( ) )
461
+ } ) ?;
489
462
}
490
- self . use_ecx ( source_info, |this| {
491
- let l = this. ecx . read_immediate ( this. ecx . eval_operand ( left, None ) ?) ?;
492
- let ( _, overflow, _ty) = this. ecx . overflowing_binary_op ( * op, l, r) ?;
493
-
494
- // We check overflow in debug mode already
495
- // so should only check in release mode.
496
- if !this. tcx . sess . overflow_checks ( ) && overflow {
497
- let err = err_panic ! ( Overflow ( * op) ) . into ( ) ;
498
- return Err ( err) ;
463
+
464
+ Rvalue :: BinaryOp ( op, left, right) => {
465
+ trace ! ( "checking BinaryOp(op = {:?}, left = {:?}, right = {:?})" , op, left, right) ;
466
+
467
+ let r = self . use_ecx ( source_info, |this| {
468
+ this. ecx . read_immediate ( this. ecx . eval_operand ( right, None ) ?)
469
+ } ) ?;
470
+ if * op == BinOp :: Shr || * op == BinOp :: Shl {
471
+ let left_bits = place_layout. size . bits ( ) ;
472
+ let right_size = r. layout . size ;
473
+ let r_bits = r. to_scalar ( ) . and_then ( |r| r. to_bits ( right_size) ) ;
474
+ if r_bits. ok ( ) . map_or ( false , |b| b >= left_bits as u128 ) {
475
+ let source_scope_local_data = match self . source_scope_local_data {
476
+ ClearCrossCrate :: Set ( ref data) => data,
477
+ ClearCrossCrate :: Clear => return None ,
478
+ } ;
479
+ let dir = if * op == BinOp :: Shr {
480
+ "right"
481
+ } else {
482
+ "left"
483
+ } ;
484
+ let hir_id = source_scope_local_data[ source_info. scope ] . lint_root ;
485
+ self . tcx . lint_hir (
486
+ :: rustc:: lint:: builtin:: EXCEEDING_BITSHIFTS ,
487
+ hir_id,
488
+ span,
489
+ & format ! ( "attempt to shift {} with overflow" , dir) ) ;
490
+ return None ;
491
+ }
499
492
}
493
+ self . use_ecx ( source_info, |this| {
494
+ let l = this. ecx . read_immediate ( this. ecx . eval_operand ( left, None ) ?) ?;
495
+ let ( _, overflow, _ty) = this. ecx . overflowing_binary_op ( * op, l, r) ?;
496
+
497
+ // We check overflow in debug mode already
498
+ // so should only check in release mode.
499
+ if !this. tcx . sess . overflow_checks ( ) && overflow {
500
+ let err = err_panic ! ( Overflow ( * op) ) . into ( ) ;
501
+ return Err ( err) ;
502
+ }
500
503
501
- Ok ( ( ) )
502
- } ) ?;
503
- } else if let Rvalue :: Ref ( _, _, place) = rvalue {
504
- trace ! ( "checking Ref({:?})" , place) ;
505
- // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref
506
- // from a function argument that hasn't been assigned to in this function.
507
- if let Place {
508
- base : PlaceBase :: Local ( local) ,
509
- projection : box [ ]
510
- } = place {
504
+ Ok ( ( ) )
505
+ } ) ?;
506
+ }
507
+
508
+ Rvalue :: Ref ( _, _, Place { base : PlaceBase :: Local ( local) , projection : box [ ] } ) => {
509
+ trace ! ( "checking Ref({:?})" , place) ;
510
+ // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref
511
+ // from a function argument that hasn't been assigned to in this function.
511
512
let alive =
512
513
if let LocalValue :: Live ( _) = self . ecx . frame ( ) . locals [ * local] . value {
513
514
true
@@ -518,12 +519,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
518
519
return None ;
519
520
}
520
521
}
521
- } else if let Rvalue :: Aggregate ( _ , operands ) = rvalue {
522
- // FIXME(wesleywiser): const eval will turn this into a `const Scalar(<ZST>)` that
523
- // `SimplifyLocals` doesn't know it can remove.
524
- if operands . len ( ) == 0 {
522
+
523
+ Rvalue :: Aggregate ( _ , operands ) if operands . len ( ) == 0 => {
524
+ // FIXME(wesleywiser): const eval will turn this into a `const Scalar(<ZST>)` that
525
+ // `SimplifyLocals` doesn't know it can remove.
525
526
return None ;
526
527
}
528
+
529
+ _ => { }
527
530
}
528
531
529
532
self . use_ecx ( source_info, |this| {
0 commit comments