@@ -6,8 +6,9 @@ use crate::type_error_struct;
66use rustc_ast:: util:: parser:: PREC_POSTFIX ;
77use rustc_errors:: { struct_span_err, Applicability , Diagnostic , ErrorGuaranteed , StashKey } ;
88use rustc_hir as hir;
9- use rustc_hir:: def:: { self , CtorKind , Namespace , Res } ;
9+ use rustc_hir:: def:: { self , CtorKind , DefKind , Namespace , Res } ;
1010use rustc_hir:: def_id:: DefId ;
11+ use rustc_hir:: HirId ;
1112use rustc_hir_analysis:: autoderef:: Autoderef ;
1213use rustc_infer:: {
1314 infer,
@@ -376,15 +377,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
376377 expected : Expectation < ' tcx > ,
377378 ) -> Ty < ' tcx > {
378379 let ( fn_sig, def_id) = match * callee_ty. kind ( ) {
379- ty:: FnDef ( def_id, subst) => {
380- let fn_sig = self . tcx . fn_sig ( def_id) . subst ( self . tcx , subst) ;
380+ ty:: FnDef ( def_id, substs) => {
381+ self . enforce_context_effects ( call_expr. hir_id , call_expr. span , def_id, substs) ;
382+ let fn_sig = self . tcx . fn_sig ( def_id) . subst ( self . tcx , substs) ;
381383
382384 // Unit testing: function items annotated with
383385 // `#[rustc_evaluate_where_clauses]` trigger special output
384386 // to let us test the trait evaluation system.
385387 if self . tcx . has_attr ( def_id, sym:: rustc_evaluate_where_clauses) {
386388 let predicates = self . tcx . predicates_of ( def_id) ;
387- let predicates = predicates. instantiate ( self . tcx , subst ) ;
389+ let predicates = predicates. instantiate ( self . tcx , substs ) ;
388390 for ( predicate, predicate_span) in predicates {
389391 let obligation = Obligation :: new (
390392 self . tcx ,
@@ -405,6 +407,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
405407 }
406408 ( fn_sig, Some ( def_id) )
407409 }
410+ // FIXME(effects): these arms should error because we can't enforce them
408411 ty:: FnPtr ( sig) => ( sig, None ) ,
409412 _ => {
410413 for arg in arg_exprs {
@@ -739,6 +742,64 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
739742 fn_sig. output ( )
740743 }
741744
745+ #[ tracing:: instrument( level = "debug" , skip( self , span) ) ]
746+ pub ( super ) fn enforce_context_effects (
747+ & self ,
748+ call_expr_hir : HirId ,
749+ span : Span ,
750+ callee_did : DefId ,
751+ callee_substs : SubstsRef < ' tcx > ,
752+ ) {
753+ let tcx = self . tcx ;
754+
755+ if !tcx. features ( ) . effects || tcx. sess . opts . unstable_opts . unleash_the_miri_inside_of_you {
756+ return ;
757+ }
758+
759+ // Compute the constness required by the context.
760+ let context = tcx. hir ( ) . enclosing_body_owner ( call_expr_hir) ;
761+ let const_context = tcx. hir ( ) . body_const_context ( context) ;
762+
763+ let kind = tcx. def_kind ( context. to_def_id ( ) ) ;
764+ debug_assert_ne ! ( kind, DefKind :: ConstParam ) ;
765+
766+ if tcx. has_attr ( context. to_def_id ( ) , sym:: rustc_do_not_const_check) {
767+ trace ! ( "do not const check this context" ) ;
768+ return ;
769+ }
770+
771+ let effect = match const_context {
772+ Some ( hir:: ConstContext :: Static ( _) | hir:: ConstContext :: Const ) => tcx. consts . false_ ,
773+ Some ( hir:: ConstContext :: ConstFn ) => {
774+ let substs = ty:: InternalSubsts :: identity_for_item ( tcx, context) ;
775+ substs. host_effect_param ( ) . expect ( "ConstContext::Maybe must have host effect param" )
776+ }
777+ None => tcx. consts . true_ ,
778+ } ;
779+
780+ let identity_substs = ty:: InternalSubsts :: identity_for_item ( tcx, callee_did) ;
781+
782+ trace ! ( ?effect, ?identity_substs, ?callee_substs) ;
783+
784+ // FIXME this should be made more efficient
785+ let host_effect_param_index = identity_substs. iter ( ) . position ( |x| {
786+ matches ! ( x. unpack( ) , ty:: GenericArgKind :: Const ( const_) if matches!( const_. kind( ) , ty:: ConstKind :: Param ( param) if param. name == sym:: host) )
787+ } ) ;
788+
789+ if let Some ( idx) = host_effect_param_index {
790+ let param = callee_substs. const_at ( idx) ;
791+ let cause = self . misc ( span) ;
792+ match self . at ( & cause, self . param_env ) . eq ( infer:: DefineOpaqueTypes :: No , effect, param) {
793+ Ok ( infer:: InferOk { obligations, value : ( ) } ) => {
794+ self . register_predicates ( obligations) ;
795+ }
796+ Err ( e) => {
797+ self . err_ctxt ( ) . report_mismatched_consts ( & cause, effect, param, e) . emit ( ) ;
798+ }
799+ }
800+ }
801+ }
802+
742803 fn confirm_overloaded_call (
743804 & self ,
744805 call_expr : & ' tcx hir:: Expr < ' tcx > ,
0 commit comments