@@ -11,7 +11,6 @@ use rustc_hir::def_id::DefId;
1111use  rustc_hir:: { self  as  hir,  LangItem } ; 
1212use  rustc_index:: bit_set:: BitSet ; 
1313use  rustc_infer:: infer:: TyCtxtInferExt ; 
14- use  rustc_infer:: traits:: ObligationCause ; 
1514use  rustc_middle:: mir:: visit:: Visitor ; 
1615use  rustc_middle:: mir:: * ; 
1716use  rustc_middle:: span_bug; 
@@ -20,9 +19,11 @@ use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TypeVisitableExt, Typin
2019use  rustc_mir_dataflow:: Analysis ; 
2120use  rustc_mir_dataflow:: impls:: MaybeStorageLive ; 
2221use  rustc_mir_dataflow:: storage:: always_storage_live_locals; 
23- use  rustc_span:: { DUMMY_SP ,   Span ,  Symbol ,  sym} ; 
22+ use  rustc_span:: { Span ,  Symbol ,  sym} ; 
2423use  rustc_trait_selection:: error_reporting:: InferCtxtErrorExt ; 
25- use  rustc_trait_selection:: traits:: { self ,  ObligationCauseCode ,  ObligationCtxt } ; 
24+ use  rustc_trait_selection:: traits:: { 
25+     Obligation ,  ObligationCause ,  ObligationCauseCode ,  ObligationCtxt , 
26+ } ; 
2627use  tracing:: { debug,  instrument,  trace} ; 
2728
2829use  super :: ops:: { self ,  NonConstOp ,  Status } ; 
@@ -360,6 +361,73 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
360361        // end of evaluation. 
361362        !is_transient
362363    } 
364+ 
365+     fn  revalidate_conditional_constness ( 
366+         & mut  self , 
367+         callee :  DefId , 
368+         callee_args :  ty:: GenericArgsRef < ' tcx > , 
369+         call_source :  CallSource , 
370+         call_span :  Span , 
371+     )  { 
372+         let  tcx = self . tcx ; 
373+         if  !tcx. is_conditionally_const ( callee)  { 
374+             return ; 
375+         } 
376+ 
377+         let  const_conditions = tcx. const_conditions ( callee) . instantiate ( tcx,  callee_args) ; 
378+         // If there are any const conditions on this fn and `const_trait_impl` 
379+         // is not enabled, simply bail. We shouldn't be able to call conditionally 
380+         // const functions on stable. 
381+         if  !const_conditions. is_empty ( )  && !tcx. features ( ) . const_trait_impl ( )  { 
382+             self . check_op ( ops:: FnCallNonConst  { 
383+                 callee, 
384+                 args :  callee_args, 
385+                 span :  call_span, 
386+                 call_source, 
387+                 feature :  Some ( sym:: const_trait_impl) , 
388+             } ) ; 
389+             return ; 
390+         } 
391+ 
392+         let  infcx = tcx. infer_ctxt ( ) . build ( TypingMode :: from_param_env ( self . param_env ) ) ; 
393+         let  ocx = ObligationCtxt :: new_with_diagnostics ( & infcx) ; 
394+ 
395+         let  body_id = self . body . source . def_id ( ) . expect_local ( ) ; 
396+         let  host_polarity = match  self . const_kind ( )  { 
397+             hir:: ConstContext :: ConstFn  => ty:: BoundConstness :: Maybe , 
398+             hir:: ConstContext :: Static ( _)  | hir:: ConstContext :: Const  {  .. }  => { 
399+                 ty:: BoundConstness :: Const 
400+             } 
401+         } ; 
402+         let  const_conditions = ocx. normalize ( 
403+             & ObligationCause :: misc ( call_span,  body_id) , 
404+             self . param_env , 
405+             const_conditions, 
406+         ) ; 
407+         ocx. register_obligations ( const_conditions. into_iter ( ) . map ( |( trait_ref,  span) | { 
408+             Obligation :: new ( 
409+                 tcx, 
410+                 ObligationCause :: new ( 
411+                     call_span, 
412+                     body_id, 
413+                     ObligationCauseCode :: WhereClause ( callee,  span) , 
414+                 ) , 
415+                 self . param_env , 
416+                 trait_ref. to_host_effect_clause ( tcx,  host_polarity) , 
417+             ) 
418+         } ) ) ; 
419+ 
420+         let  errors = ocx. select_all_or_error ( ) ; 
421+         if  !errors. is_empty ( )  { 
422+             // FIXME(effects): Soon this should be unconditionally delaying a bug. 
423+             if  matches ! ( call_source,  CallSource :: Normal )  && tcx. features ( ) . effects ( )  { 
424+                 tcx. dcx ( ) 
425+                     . span_delayed_bug ( call_span,  "this should have reported a ~const error in HIR" ) ; 
426+             }  else  { 
427+                 infcx. err_ctxt ( ) . report_fulfillment_errors ( errors) ; 
428+             } 
429+         } 
430+     } 
363431} 
364432
365433impl < ' tcx >  Visitor < ' tcx >  for  Checker < ' _ ,  ' tcx >  { 
@@ -566,7 +634,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
566634                } ; 
567635
568636                let  ConstCx  {  tcx,  body,  param_env,  .. }  = * self . ccx ; 
569-                 let  caller = self . def_id ( ) ; 
570637
571638                let  fn_ty = func. ty ( body,  tcx) ; 
572639
@@ -584,31 +651,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
584651                    } 
585652                } ; 
586653
587-                 // Check that all trait bounds that are marked as `~const` can be satisfied. 
588-                 // 
589-                 // Typeck only does a "non-const" check since it operates on HIR and cannot distinguish 
590-                 // which path expressions are getting called on and which path expressions are only used 
591-                 // as function pointers. This is required for correctness. 
592-                 let  infcx = tcx. infer_ctxt ( ) . build ( TypingMode :: from_param_env ( param_env) ) ; 
593-                 let  ocx = ObligationCtxt :: new_with_diagnostics ( & infcx) ; 
594- 
595-                 let  predicates = tcx. predicates_of ( callee) . instantiate ( tcx,  fn_args) ; 
596-                 let  cause = ObligationCause :: new ( 
597-                     terminator. source_info . span , 
598-                     self . body . source . def_id ( ) . expect_local ( ) , 
599-                     ObligationCauseCode :: WhereClause ( callee,  DUMMY_SP ) , 
600-                 ) ; 
601-                 let  normalized_predicates = ocx. normalize ( & cause,  param_env,  predicates) ; 
602-                 ocx. register_obligations ( traits:: predicates_for_generics ( 
603-                     |_,  _| cause. clone ( ) , 
604-                     self . param_env , 
605-                     normalized_predicates, 
606-                 ) ) ; 
607- 
608-                 let  errors = ocx. select_all_or_error ( ) ; 
609-                 if  !errors. is_empty ( )  { 
610-                     infcx. err_ctxt ( ) . report_fulfillment_errors ( errors) ; 
611-                 } 
654+                 self . revalidate_conditional_constness ( callee,  fn_args,  call_source,  * fn_span) ; 
612655
613656                let  mut  is_trait = false ; 
614657                // Attempting to call a trait method? 
@@ -648,7 +691,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
648691                            None 
649692                        } ; 
650693                        self . check_op ( ops:: FnCallNonConst  { 
651-                             caller, 
652694                            callee, 
653695                            args :  fn_args, 
654696                            span :  * fn_span, 
@@ -738,7 +780,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
738780                // Trait functions are not `const fn` so we have to skip them here. 
739781                if  !tcx. is_const_fn ( callee)  && !is_trait { 
740782                    self . check_op ( ops:: FnCallNonConst  { 
741-                         caller, 
742783                        callee, 
743784                        args :  fn_args, 
744785                        span :  * fn_span, 
0 commit comments