@@ -3917,75 +3917,99 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
39173917 expected : Ty < ' tcx > ,
39183918 found : Ty < ' tcx > ,
39193919 ) -> bool {
3920- match found. sty {
3921- ty:: FnDef ( ..) | ty:: FnPtr ( _) => { }
3922- _ => return false ,
3923- }
39243920 let hir = self . tcx . hir ( ) ;
3921+ let ( def_id, sig) = match found. sty {
3922+ ty:: FnDef ( def_id, _) => ( def_id, found. fn_sig ( self . tcx ) ) ,
3923+ ty:: Closure ( def_id, substs) => {
3924+ // We don't use `closure_sig` to account for malformed closures like
3925+ // `|_: [_; continue]| {}` and instead we don't suggest anything.
3926+ let closure_sig_ty = substs. closure_sig_ty ( def_id, self . tcx ) ;
3927+ ( def_id, match closure_sig_ty. sty {
3928+ ty:: FnPtr ( sig) => sig,
3929+ _ => return false ,
3930+ } )
3931+ }
3932+ _ => return false ,
3933+ } ;
39253934
3926- let sig = found. fn_sig ( self . tcx ) ;
39273935 let sig = self
39283936 . replace_bound_vars_with_fresh_vars ( expr. span , infer:: FnCall , & sig)
39293937 . 0 ;
39303938 let sig = self . normalize_associated_types_in ( expr. span , & sig) ;
3931- if let Ok ( _ ) = self . try_coerce ( expr , sig. output ( ) , expected, AllowTwoPhase :: No ) {
3939+ if self . can_coerce ( sig. output ( ) , expected) {
39323940 let ( mut sugg_call, applicability) = if sig. inputs ( ) . is_empty ( ) {
39333941 ( String :: new ( ) , Applicability :: MachineApplicable )
39343942 } else {
39353943 ( "..." . to_string ( ) , Applicability :: HasPlaceholders )
39363944 } ;
39373945 let mut msg = "call this function" ;
3938- if let ty:: FnDef ( def_id, ..) = found. sty {
3939- match hir. get_if_local ( def_id) {
3940- Some ( Node :: Item ( hir:: Item {
3941- node : ItemKind :: Fn ( .., body_id) ,
3942- ..
3943- } ) ) |
3944- Some ( Node :: ImplItem ( hir:: ImplItem {
3945- node : hir:: ImplItemKind :: Method ( _, body_id) ,
3946- ..
3947- } ) ) |
3948- Some ( Node :: TraitItem ( hir:: TraitItem {
3949- node : hir:: TraitItemKind :: Method ( .., hir:: TraitMethod :: Provided ( body_id) ) ,
3950- ..
3951- } ) ) => {
3952- let body = hir. body ( * body_id) ;
3953- sugg_call = body. arguments . iter ( )
3954- . map ( |arg| match & arg. pat . node {
3955- hir:: PatKind :: Binding ( _, _, ident, None )
3956- if ident. name != kw:: SelfLower => ident. to_string ( ) ,
3957- _ => "_" . to_string ( ) ,
3958- } ) . collect :: < Vec < _ > > ( ) . join ( ", " ) ;
3946+ match hir. get_if_local ( def_id) {
3947+ Some ( Node :: Item ( hir:: Item {
3948+ node : ItemKind :: Fn ( .., body_id) ,
3949+ ..
3950+ } ) ) |
3951+ Some ( Node :: ImplItem ( hir:: ImplItem {
3952+ node : hir:: ImplItemKind :: Method ( _, body_id) ,
3953+ ..
3954+ } ) ) |
3955+ Some ( Node :: TraitItem ( hir:: TraitItem {
3956+ node : hir:: TraitItemKind :: Method ( .., hir:: TraitMethod :: Provided ( body_id) ) ,
3957+ ..
3958+ } ) ) => {
3959+ let body = hir. body ( * body_id) ;
3960+ sugg_call = body. arguments . iter ( )
3961+ . map ( |arg| match & arg. pat . node {
3962+ hir:: PatKind :: Binding ( _, _, ident, None )
3963+ if ident. name != kw:: SelfLower => ident. to_string ( ) ,
3964+ _ => "_" . to_string ( ) ,
3965+ } ) . collect :: < Vec < _ > > ( ) . join ( ", " ) ;
3966+ }
3967+ Some ( Node :: Expr ( hir:: Expr {
3968+ node : ExprKind :: Closure ( _, _, body_id, closure_span, _) ,
3969+ span : full_closure_span,
3970+ ..
3971+ } ) ) => {
3972+ if * full_closure_span == expr. span {
3973+ return false ;
39593974 }
3960- Some ( Node :: Ctor ( hir:: VariantData :: Tuple ( fields, _) ) ) => {
3961- sugg_call = fields. iter ( ) . map ( |_| "_" ) . collect :: < Vec < _ > > ( ) . join ( ", " ) ;
3962- match hir. as_local_hir_id ( def_id) . and_then ( |hir_id| hir. def_kind ( hir_id) ) {
3963- Some ( hir:: def:: DefKind :: Ctor ( hir:: def:: CtorOf :: Variant , _) ) => {
3964- msg = "instantiate this tuple variant" ;
3965- }
3966- Some ( hir:: def:: DefKind :: Ctor ( hir:: def:: CtorOf :: Struct , _) ) => {
3967- msg = "instantiate this tuple struct" ;
3968- }
3969- _ => { }
3975+ err. span_label ( * closure_span, "closure defined here" ) ;
3976+ msg = "call this closure" ;
3977+ let body = hir. body ( * body_id) ;
3978+ sugg_call = body. arguments . iter ( )
3979+ . map ( |arg| match & arg. pat . node {
3980+ hir:: PatKind :: Binding ( _, _, ident, None )
3981+ if ident. name != kw:: SelfLower => ident. to_string ( ) ,
3982+ _ => "_" . to_string ( ) ,
3983+ } ) . collect :: < Vec < _ > > ( ) . join ( ", " ) ;
3984+ }
3985+ Some ( Node :: Ctor ( hir:: VariantData :: Tuple ( fields, _) ) ) => {
3986+ sugg_call = fields. iter ( ) . map ( |_| "_" ) . collect :: < Vec < _ > > ( ) . join ( ", " ) ;
3987+ match hir. as_local_hir_id ( def_id) . and_then ( |hir_id| hir. def_kind ( hir_id) ) {
3988+ Some ( hir:: def:: DefKind :: Ctor ( hir:: def:: CtorOf :: Variant , _) ) => {
3989+ msg = "instantiate this tuple variant" ;
39703990 }
3991+ Some ( hir:: def:: DefKind :: Ctor ( hir:: def:: CtorOf :: Struct , _) ) => {
3992+ msg = "instantiate this tuple struct" ;
3993+ }
3994+ _ => { }
39713995 }
3972- Some ( Node :: ForeignItem ( hir:: ForeignItem {
3973- node : hir:: ForeignItemKind :: Fn ( _, idents, _) ,
3974- ..
3975- } ) ) |
3976- Some ( Node :: TraitItem ( hir:: TraitItem {
3977- node : hir:: TraitItemKind :: Method ( .., hir:: TraitMethod :: Required ( idents) ) ,
3978- ..
3979- } ) ) => sugg_call = idents. iter ( )
3980- . map ( |ident| if ident. name != kw:: SelfLower {
3981- ident. to_string ( )
3982- } else {
3983- "_" . to_string ( )
3984- } ) . collect :: < Vec < _ > > ( )
3985- . join ( ", " ) ,
3986- _ => { }
39873996 }
3988- } ;
3997+ Some ( Node :: ForeignItem ( hir:: ForeignItem {
3998+ node : hir:: ForeignItemKind :: Fn ( _, idents, _) ,
3999+ ..
4000+ } ) ) |
4001+ Some ( Node :: TraitItem ( hir:: TraitItem {
4002+ node : hir:: TraitItemKind :: Method ( .., hir:: TraitMethod :: Required ( idents) ) ,
4003+ ..
4004+ } ) ) => sugg_call = idents. iter ( )
4005+ . map ( |ident| if ident. name != kw:: SelfLower {
4006+ ident. to_string ( )
4007+ } else {
4008+ "_" . to_string ( )
4009+ } ) . collect :: < Vec < _ > > ( )
4010+ . join ( ", " ) ,
4011+ _ => { }
4012+ }
39894013 if let Ok ( code) = self . sess ( ) . source_map ( ) . span_to_snippet ( expr. span ) {
39904014 err. span_suggestion (
39914015 expr. span ,
0 commit comments