@@ -688,7 +688,6 @@ impl<'tcx> Validator<'_, 'tcx> {
688688 }
689689}
690690
691- // FIXME(eddyb) remove the differences for promotability in `static`, `const`, `const fn`.
692691fn validate_candidates (
693692 ccx : & ConstCx < ' _ , ' _ > ,
694693 temps : & mut IndexSlice < Local , TempState > ,
@@ -713,6 +712,10 @@ struct Promoter<'a, 'tcx> {
713712 /// If true, all nested temps are also kept in the
714713 /// source MIR, not moved to the promoted MIR.
715714 keep_original : bool ,
715+
716+ /// If true, add the new const (the promoted) to the required_consts of the parent MIR.
717+ /// This is initially false and then set by the visitor when it encounters a `Call` terminator.
718+ add_to_required : bool ,
716719}
717720
718721impl < ' a , ' tcx > Promoter < ' a , ' tcx > {
@@ -815,6 +818,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
815818 TerminatorKind :: Call {
816819 mut func, mut args, call_source : desugar, fn_span, ..
817820 } => {
821+ // This promoted involves a function call, so it may fail to evaluate.
822+ // Let's make sure it is added to `required_consts` so that that failure cannot get lost.
823+ self . add_to_required = true ;
824+
818825 self . visit_operand ( & mut func, loc) ;
819826 for arg in & mut args {
820827 self . visit_operand ( & mut arg. node , loc) ;
@@ -849,7 +856,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
849856
850857 fn promote_candidate ( mut self , candidate : Candidate , next_promoted_id : usize ) -> Body < ' tcx > {
851858 let def = self . source . source . def_id ( ) ;
852- let mut rvalue = {
859+ let ( mut rvalue, promoted_op ) = {
853860 let promoted = & mut self . promoted ;
854861 let promoted_id = Promoted :: new ( next_promoted_id) ;
855862 let tcx = self . tcx ;
@@ -859,11 +866,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
859866 let args = tcx. erase_regions ( GenericArgs :: identity_for_item ( tcx, def) ) ;
860867 let uneval = mir:: UnevaluatedConst { def, args, promoted : Some ( promoted_id) } ;
861868
862- Operand :: Constant ( Box :: new ( ConstOperand {
863- span,
864- user_ty : None ,
865- const_ : Const :: Unevaluated ( uneval, ty) ,
866- } ) )
869+ ConstOperand { span, user_ty : None , const_ : Const :: Unevaluated ( uneval, ty) }
867870 } ;
868871
869872 let blocks = self . source . basic_blocks . as_mut ( ) ;
@@ -896,22 +899,26 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
896899 let promoted_ref = local_decls. push ( promoted_ref) ;
897900 assert_eq ! ( self . temps. push( TempState :: Unpromotable ) , promoted_ref) ;
898901
902+ let promoted_operand = promoted_operand ( ref_ty, span) ;
899903 let promoted_ref_statement = Statement {
900904 source_info : statement. source_info ,
901905 kind : StatementKind :: Assign ( Box :: new ( (
902906 Place :: from ( promoted_ref) ,
903- Rvalue :: Use ( promoted_operand ( ref_ty , span ) ) ,
907+ Rvalue :: Use ( Operand :: Constant ( Box :: new ( promoted_operand ) ) ) ,
904908 ) ) ) ,
905909 } ;
906910 self . extra_statements . push ( ( loc, promoted_ref_statement) ) ;
907911
908- Rvalue :: Ref (
909- tcx. lifetimes . re_erased ,
910- * borrow_kind,
911- Place {
912- local : mem:: replace ( & mut place. local , promoted_ref) ,
913- projection : List :: empty ( ) ,
914- } ,
912+ (
913+ Rvalue :: Ref (
914+ tcx. lifetimes . re_erased ,
915+ * borrow_kind,
916+ Place {
917+ local : mem:: replace ( & mut place. local , promoted_ref) ,
918+ projection : List :: empty ( ) ,
919+ } ,
920+ ) ,
921+ promoted_operand,
915922 )
916923 } ;
917924
@@ -923,6 +930,12 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
923930
924931 let span = self . promoted . span ;
925932 self . assign ( RETURN_PLACE , rvalue, span) ;
933+
934+ // Now that we did promotion, we know whether we'll want to add this to `required_consts`.
935+ if self . add_to_required {
936+ self . source . required_consts . push ( promoted_op) ;
937+ }
938+
926939 self . promoted
927940 }
928941}
@@ -982,6 +995,11 @@ fn promote_candidates<'tcx>(
982995 None ,
983996 body. tainted_by_errors ,
984997 ) ;
998+ // We keep `required_consts` of the new MIR body empty. All consts mentioned here have
999+ // already been added to the parent MIR's `required_consts` (that is computed before
1000+ // promotion), and no matter where this promoted const ends up, our parent MIR must be
1001+ // somewhere in the reachable dependency chain so we can rely on its required consts being
1002+ // evaluated.
9851003 promoted. phase = MirPhase :: Analysis ( AnalysisPhase :: Initial ) ;
9861004
9871005 let promoter = Promoter {
@@ -991,6 +1009,7 @@ fn promote_candidates<'tcx>(
9911009 temps : & mut temps,
9921010 extra_statements : & mut extra_statements,
9931011 keep_original : false ,
1012+ add_to_required : false ,
9941013 } ;
9951014
9961015 let mut promoted = promoter. promote_candidate ( candidate, promotions. len ( ) ) ;
0 commit comments