@@ -16,7 +16,7 @@ use rustc_middle::mir::visit::{
1616use rustc_middle:: mir:: * ;
1717use rustc_middle:: ty:: layout:: { LayoutError , LayoutOf , LayoutOfHelpers , TyAndLayout } ;
1818use rustc_middle:: ty:: InternalSubsts ;
19- use rustc_middle:: ty:: { self , ConstKind , Instance , ParamEnv , Ty , TyCtxt , TypeVisitable } ;
19+ use rustc_middle:: ty:: { self , Instance , ParamEnv , Ty , TyCtxt , TypeVisitable } ;
2020use rustc_span:: { def_id:: DefId , Span } ;
2121use rustc_target:: abi:: { self , Align , HasDataLayout , Size , TargetDataLayout } ;
2222use rustc_target:: spec:: abi:: Abi as CallAbi ;
@@ -625,21 +625,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
625625
626626 fn replace_with_const (
627627 & mut self ,
628- rval : & mut Rvalue < ' tcx > ,
629628 value : & OpTy < ' tcx > ,
630629 source_info : SourceInfo ,
631- ) {
632- if let Rvalue :: Use ( Operand :: Constant ( c) ) = rval {
633- match c. literal {
634- ConstantKind :: Ty ( c) if matches ! ( c. kind( ) , ConstKind :: Unevaluated ( ..) ) => { }
635- _ => {
636- trace ! ( "skipping replace of Rvalue::Use({:?} because it is already a const" , c) ;
637- return ;
638- }
639- }
640- }
641-
642- trace ! ( "attempting to replace {:?} with {:?}" , rval, value) ;
630+ ) -> Option < Operand < ' tcx > > {
631+ trace ! ( "attempting to replace with {:?}" , value) ;
643632 if let Err ( e) = self . ecx . const_validate_operand (
644633 value,
645634 vec ! [ ] ,
@@ -649,64 +638,56 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
649638 CtfeValidationMode :: Regular ,
650639 ) {
651640 trace ! ( "validation error, attempt failed: {:?}" , e) ;
652- return ;
641+ return None ;
653642 }
654643
655644 // FIXME> figure out what to do when read_immediate_raw fails
656645 let imm = self . ecx . read_immediate_raw ( value) . ok ( ) ;
657646
658- if let Some ( Right ( imm) ) = imm {
659- match * imm {
660- interpret:: Immediate :: Scalar ( scalar) => {
661- * rval = Rvalue :: Use ( self . operand_from_scalar (
662- scalar,
663- value. layout . ty ,
664- source_info. span ,
665- ) ) ;
666- }
667- Immediate :: ScalarPair ( ..) => {
668- // Found a value represented as a pair. For now only do const-prop if the type
669- // of `rvalue` is also a tuple with two scalars.
670- // FIXME: enable the general case stated above ^.
671- let ty = value. layout . ty ;
672- // Only do it for tuples
673- if let ty:: Tuple ( types) = ty. kind ( ) {
674- // Only do it if tuple is also a pair with two scalars
675- if let [ ty1, ty2] = types[ ..] {
676- let ty_is_scalar = |ty| {
677- self . ecx . layout_of ( ty) . ok ( ) . map ( |layout| layout. abi . is_scalar ( ) )
678- == Some ( true )
679- } ;
680- let alloc = if ty_is_scalar ( ty1) && ty_is_scalar ( ty2) {
681- let alloc = self
682- . ecx
683- . intern_with_temp_alloc ( value. layout , |ecx, dest| {
684- ecx. write_immediate ( * imm, dest)
685- } )
686- . unwrap ( ) ;
687- Some ( alloc)
688- } else {
689- None
690- } ;
691-
692- if let Some ( alloc) = alloc {
693- // Assign entire constant in a single statement.
694- // We can't use aggregates, as we run after the aggregate-lowering `MirPhase`.
695- let const_val = ConstValue :: ByRef { alloc, offset : Size :: ZERO } ;
696- let literal = ConstantKind :: Val ( const_val, ty) ;
697- * rval = Rvalue :: Use ( Operand :: Constant ( Box :: new ( Constant {
698- span : source_info. span ,
699- user_ty : None ,
700- literal,
701- } ) ) ) ;
702- }
703- }
704- }
647+ let Right ( imm) = imm? else { return None } ;
648+ match * imm {
649+ interpret:: Immediate :: Scalar ( scalar) => {
650+ Some ( self . operand_from_scalar ( scalar, value. layout . ty , source_info. span ) )
651+ }
652+ Immediate :: ScalarPair ( ..) => {
653+ // Found a value represented as a pair. For now only do const-prop if the type
654+ // of `rvalue` is also a tuple with two scalars.
655+ // FIXME: enable the general case stated above ^.
656+ let ty = value. layout . ty ;
657+ // Only do it for tuples
658+ let ty:: Tuple ( types) = ty. kind ( ) else { return None } ;
659+ // Only do it if tuple is also a pair with two scalars
660+ if let [ ty1, ty2] = types[ ..] {
661+ let ty_is_scalar = |ty| {
662+ self . ecx . layout_of ( ty) . ok ( ) . map ( |layout| layout. abi . is_scalar ( ) )
663+ == Some ( true )
664+ } ;
665+ let alloc = if ty_is_scalar ( ty1) && ty_is_scalar ( ty2) {
666+ self . ecx
667+ . intern_with_temp_alloc ( value. layout , |ecx, dest| {
668+ ecx. write_immediate ( * imm, dest)
669+ } )
670+ . unwrap ( )
671+ } else {
672+ return None ;
673+ } ;
674+
675+ // Assign entire constant in a single statement.
676+ // We can't use aggregates, as we run after the aggregate-lowering `MirPhase`.
677+ let const_val = ConstValue :: ByRef { alloc, offset : Size :: ZERO } ;
678+ let literal = ConstantKind :: Val ( const_val, ty) ;
679+ Some ( Operand :: Constant ( Box :: new ( Constant {
680+ span : source_info. span ,
681+ user_ty : None ,
682+ literal,
683+ } ) ) )
684+ } else {
685+ None
705686 }
706- // Scalars or scalar pairs that contain undef values are assumed to not have
707- // successfully evaluated and are thus not propagated.
708- _ => { }
709687 }
688+ // Scalars or scalar pairs that contain undef values are assumed to not have
689+ // successfully evaluated and are thus not propagated.
690+ _ => None ,
710691 }
711692 }
712693
@@ -899,7 +880,9 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
899880 // consists solely of uninitialized memory (so it doesn't capture any locals).
900881 if let Some ( ref value) = self . get_const ( place) && self . should_const_prop ( value) {
901882 trace ! ( "replacing {:?} with {:?}" , rval, value) ;
902- self . replace_with_const ( rval, value, source_info) ;
883+ if let Some ( operand) = self . replace_with_const ( value, source_info) {
884+ * rval = Rvalue :: Use ( operand) ;
885+ }
903886 if can_const_prop == ConstPropMode :: FullConstProp
904887 || can_const_prop == ConstPropMode :: OnlyInsideOwnBlock
905888 {
0 commit comments