@@ -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};
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 ( self . body . typing_mode ( tcx) ) ;
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 ( body. typing_mode ( tcx) ) ;
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