@@ -6,8 +6,9 @@ use crate::type_error_struct;
6
6
use rustc_ast:: util:: parser:: PREC_POSTFIX ;
7
7
use rustc_errors:: { struct_span_err, Applicability , Diagnostic , ErrorGuaranteed , StashKey } ;
8
8
use rustc_hir as hir;
9
- use rustc_hir:: def:: { self , CtorKind , Namespace , Res } ;
9
+ use rustc_hir:: def:: { self , CtorKind , DefKind , Namespace , Res } ;
10
10
use rustc_hir:: def_id:: DefId ;
11
+ use rustc_hir:: HirId ;
11
12
use rustc_hir_analysis:: autoderef:: Autoderef ;
12
13
use rustc_infer:: {
13
14
infer,
@@ -376,15 +377,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
376
377
expected : Expectation < ' tcx > ,
377
378
) -> Ty < ' tcx > {
378
379
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) ;
381
383
382
384
// Unit testing: function items annotated with
383
385
// `#[rustc_evaluate_where_clauses]` trigger special output
384
386
// to let us test the trait evaluation system.
385
387
if self . tcx . has_attr ( def_id, sym:: rustc_evaluate_where_clauses) {
386
388
let predicates = self . tcx . predicates_of ( def_id) ;
387
- let predicates = predicates. instantiate ( self . tcx , subst ) ;
389
+ let predicates = predicates. instantiate ( self . tcx , substs ) ;
388
390
for ( predicate, predicate_span) in predicates {
389
391
let obligation = Obligation :: new (
390
392
self . tcx ,
@@ -405,6 +407,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
405
407
}
406
408
( fn_sig, Some ( def_id) )
407
409
}
410
+ // FIXME(effects): these arms should error because we can't enforce them
408
411
ty:: FnPtr ( sig) => ( sig, None ) ,
409
412
_ => {
410
413
for arg in arg_exprs {
@@ -739,6 +742,64 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
739
742
fn_sig. output ( )
740
743
}
741
744
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
+
742
803
fn confirm_overloaded_call (
743
804
& self ,
744
805
call_expr : & ' tcx hir:: Expr < ' tcx > ,
0 commit comments