@@ -3,12 +3,14 @@ use super::method::MethodCallee;
33use super :: { Expectation , FnCtxt , TupleArgumentsFlag } ;
44
55use crate :: type_error_struct;
6+ use hir:: LangItem ;
67use rustc_ast:: util:: parser:: PREC_POSTFIX ;
78use rustc_errors:: { struct_span_err, Applicability , Diagnostic , ErrorGuaranteed , StashKey } ;
89use rustc_hir as hir;
910use rustc_hir:: def:: { self , CtorKind , Namespace , Res } ;
1011use rustc_hir:: def_id:: DefId ;
1112use rustc_hir_analysis:: autoderef:: Autoderef ;
13+ use rustc_infer:: traits:: ObligationCauseCode ;
1214use rustc_infer:: {
1315 infer,
1416 traits:: { self , Obligation } ,
@@ -22,7 +24,6 @@ use rustc_middle::ty::adjustment::{
2224} ;
2325use rustc_middle:: ty:: SubstsRef ;
2426use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeVisitableExt } ;
25- use rustc_span:: def_id:: LocalDefId ;
2627use rustc_span:: symbol:: { sym, Ident } ;
2728use rustc_span:: Span ;
2829use rustc_target:: spec:: abi;
@@ -66,7 +67,7 @@ pub fn check_legal_trait_for_method_call(
6667#[ derive( Debug ) ]
6768enum CallStep < ' tcx > {
6869 Builtin ( Ty < ' tcx > ) ,
69- DeferredClosure ( LocalDefId , ty:: FnSig < ' tcx > ) ,
70+ DeferredClosure ( Ty < ' tcx > , ty:: FnSig < ' tcx > ) ,
7071 /// E.g., enum variant constructors.
7172 Overloaded ( MethodCallee < ' tcx > ) ,
7273}
@@ -173,7 +174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
173174 closure_substs : substs,
174175 } ,
175176 ) ;
176- return Some ( CallStep :: DeferredClosure ( def_id , closure_sig) ) ;
177+ return Some ( CallStep :: DeferredClosure ( adjusted_ty , closure_sig) ) ;
177178 }
178179 }
179180
@@ -375,7 +376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
375376 arg_exprs : & ' tcx [ hir:: Expr < ' tcx > ] ,
376377 expected : Expectation < ' tcx > ,
377378 ) -> Ty < ' tcx > {
378- let ( fn_sig, def_id ) = match * callee_ty. kind ( ) {
379+ let fn_sig = match * callee_ty. kind ( ) {
379380 ty:: FnDef ( def_id, subst) => {
380381 let fn_sig = self . tcx . fn_sig ( def_id) . subst ( self . tcx , subst) ;
381382
@@ -403,9 +404,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
403404 . emit ( ) ;
404405 }
405406 }
406- ( fn_sig, Some ( def_id ) )
407+ fn_sig
407408 }
408- ty:: FnPtr ( sig) => ( sig, None ) ,
409+ ty:: FnPtr ( sig) => sig,
409410 _ => {
410411 for arg in arg_exprs {
411412 self . check_expr ( arg) ;
@@ -459,7 +460,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
459460 arg_exprs,
460461 fn_sig. c_variadic ,
461462 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 ( ) ,
463471 ) ;
464472
465473 if fn_sig. abi == abi:: Abi :: RustCall {
@@ -705,12 +713,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
705713 err. emit ( )
706714 }
707715
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+
708741 fn confirm_deferred_closure_call (
709742 & self ,
710743 call_expr : & ' tcx hir:: Expr < ' tcx > ,
711744 arg_exprs : & ' tcx [ hir:: Expr < ' tcx > ] ,
712745 expected : Expectation < ' tcx > ,
713- closure_def_id : LocalDefId ,
746+ closure_ty : Ty < ' tcx > ,
714747 fn_sig : ty:: FnSig < ' tcx > ,
715748 ) -> Ty < ' tcx > {
716749 // `fn_sig` is the *signature* of the closure being called. We
@@ -733,7 +766,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
733766 arg_exprs,
734767 fn_sig. c_variadic ,
735768 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 ( ) ,
737777 ) ;
738778
739779 fn_sig. output ( )
@@ -804,6 +844,12 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> {
804844 let mut adjustments = self . adjustments ;
805845 adjustments. extend ( autoref) ;
806846 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+ ) ;
807853
808854 fcx. write_method_call ( self . call_expr . hir_id , method_callee) ;
809855 }
0 commit comments