@@ -3,12 +3,14 @@ use super::method::MethodCallee;
3
3
use super :: { Expectation , FnCtxt , TupleArgumentsFlag } ;
4
4
5
5
use crate :: type_error_struct;
6
+ use hir:: LangItem ;
6
7
use rustc_ast:: util:: parser:: PREC_POSTFIX ;
7
8
use rustc_errors:: { struct_span_err, Applicability , Diagnostic , ErrorGuaranteed , StashKey } ;
8
9
use rustc_hir as hir;
9
10
use rustc_hir:: def:: { self , CtorKind , Namespace , Res } ;
10
11
use rustc_hir:: def_id:: DefId ;
11
12
use rustc_hir_analysis:: autoderef:: Autoderef ;
13
+ use rustc_infer:: traits:: ObligationCauseCode ;
12
14
use rustc_infer:: {
13
15
infer,
14
16
traits:: { self , Obligation } ,
@@ -22,7 +24,6 @@ use rustc_middle::ty::adjustment::{
22
24
} ;
23
25
use rustc_middle:: ty:: SubstsRef ;
24
26
use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeVisitableExt } ;
25
- use rustc_span:: def_id:: LocalDefId ;
26
27
use rustc_span:: symbol:: { sym, Ident } ;
27
28
use rustc_span:: Span ;
28
29
use rustc_target:: spec:: abi;
@@ -66,7 +67,7 @@ pub fn check_legal_trait_for_method_call(
66
67
#[ derive( Debug ) ]
67
68
enum CallStep < ' tcx > {
68
69
Builtin ( Ty < ' tcx > ) ,
69
- DeferredClosure ( LocalDefId , ty:: FnSig < ' tcx > ) ,
70
+ DeferredClosure ( Ty < ' tcx > , ty:: FnSig < ' tcx > ) ,
70
71
/// E.g., enum variant constructors.
71
72
Overloaded ( MethodCallee < ' tcx > ) ,
72
73
}
@@ -173,7 +174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
173
174
closure_substs : substs,
174
175
} ,
175
176
) ;
176
- return Some ( CallStep :: DeferredClosure ( def_id , closure_sig) ) ;
177
+ return Some ( CallStep :: DeferredClosure ( adjusted_ty , closure_sig) ) ;
177
178
}
178
179
}
179
180
@@ -375,7 +376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
375
376
arg_exprs : & ' tcx [ hir:: Expr < ' tcx > ] ,
376
377
expected : Expectation < ' tcx > ,
377
378
) -> Ty < ' tcx > {
378
- let ( fn_sig, def_id ) = match * callee_ty. kind ( ) {
379
+ let fn_sig = match * callee_ty. kind ( ) {
379
380
ty:: FnDef ( def_id, subst) => {
380
381
let fn_sig = self . tcx . fn_sig ( def_id) . subst ( self . tcx , subst) ;
381
382
@@ -403,9 +404,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
403
404
. emit ( ) ;
404
405
}
405
406
}
406
- ( fn_sig, Some ( def_id ) )
407
+ fn_sig
407
408
}
408
- ty:: FnPtr ( sig) => ( sig, None ) ,
409
+ ty:: FnPtr ( sig) => sig,
409
410
_ => {
410
411
for arg in arg_exprs {
411
412
self . check_expr ( arg) ;
@@ -459,7 +460,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
459
460
arg_exprs,
460
461
fn_sig. c_variadic ,
461
462
TupleArgumentsFlag :: DontTupleArguments ,
462
- def_id,
463
+ callee_ty,
464
+ ) ;
465
+
466
+ self . check_callable (
467
+ call_expr. hir_id ,
468
+ call_expr. span ,
469
+ callee_ty,
470
+ fn_sig. inputs ( ) . iter ( ) . copied ( ) ,
463
471
) ;
464
472
465
473
if fn_sig. abi == abi:: Abi :: RustCall {
@@ -705,12 +713,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
705
713
err. emit ( )
706
714
}
707
715
716
+ /// Enforces that things being called actually are callable
717
+ #[ instrument( skip( self , arguments) ) ]
718
+ pub ( super ) fn check_callable (
719
+ & self ,
720
+ hir_id : hir:: HirId ,
721
+ span : Span ,
722
+ callable_ty : Ty < ' tcx > ,
723
+ arguments : impl IntoIterator < Item = Ty < ' tcx > > ,
724
+ ) {
725
+ if callable_ty. references_error ( ) {
726
+ return ;
727
+ }
728
+
729
+ let cause = self . cause ( span, ObligationCauseCode :: MiscObligation ) ;
730
+
731
+ let arguments_tuple = self . tcx . mk_tup_from_iter ( arguments. into_iter ( ) ) ;
732
+ let pred = ty:: Binder :: dummy ( ty:: TraitRef :: from_lang_item (
733
+ self . tcx ,
734
+ LangItem :: Callable ,
735
+ span,
736
+ [ callable_ty, arguments_tuple] ,
737
+ ) ) ;
738
+ self . register_predicate ( Obligation :: new ( self . tcx , cause, self . param_env , pred) ) ;
739
+ }
740
+
708
741
fn confirm_deferred_closure_call (
709
742
& self ,
710
743
call_expr : & ' tcx hir:: Expr < ' tcx > ,
711
744
arg_exprs : & ' tcx [ hir:: Expr < ' tcx > ] ,
712
745
expected : Expectation < ' tcx > ,
713
- closure_def_id : LocalDefId ,
746
+ closure_ty : Ty < ' tcx > ,
714
747
fn_sig : ty:: FnSig < ' tcx > ,
715
748
) -> Ty < ' tcx > {
716
749
// `fn_sig` is the *signature* of the closure being called. We
@@ -733,7 +766,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
733
766
arg_exprs,
734
767
fn_sig. c_variadic ,
735
768
TupleArgumentsFlag :: TupleArguments ,
736
- Some ( closure_def_id. to_def_id ( ) ) ,
769
+ closure_ty,
770
+ ) ;
771
+
772
+ self . check_callable (
773
+ call_expr. hir_id ,
774
+ call_expr. span ,
775
+ closure_ty,
776
+ fn_sig. inputs ( ) [ 0 ] . tuple_fields ( ) ,
737
777
) ;
738
778
739
779
fn_sig. output ( )
@@ -804,6 +844,12 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> {
804
844
let mut adjustments = self . adjustments ;
805
845
adjustments. extend ( autoref) ;
806
846
fcx. apply_adjustments ( self . callee_expr , adjustments) ;
847
+ fcx. check_callable (
848
+ self . callee_expr . hir_id ,
849
+ self . callee_expr . span ,
850
+ fcx. tcx . mk_fn_def ( method_callee. def_id , method_callee. substs ) ,
851
+ method_sig. inputs ( ) . iter ( ) . copied ( ) ,
852
+ ) ;
807
853
808
854
fcx. write_method_call ( self . call_expr . hir_id , method_callee) ;
809
855
}
0 commit comments