@@ -3917,75 +3917,99 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3917
3917
expected : Ty < ' tcx > ,
3918
3918
found : Ty < ' tcx > ,
3919
3919
) -> bool {
3920
- match found. sty {
3921
- ty:: FnDef ( ..) | ty:: FnPtr ( _) => { }
3922
- _ => return false ,
3923
- }
3924
3920
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
+ } ;
3925
3934
3926
- let sig = found. fn_sig ( self . tcx ) ;
3927
3935
let sig = self
3928
3936
. replace_bound_vars_with_fresh_vars ( expr. span , infer:: FnCall , & sig)
3929
3937
. 0 ;
3930
3938
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) {
3932
3940
let ( mut sugg_call, applicability) = if sig. inputs ( ) . is_empty ( ) {
3933
3941
( String :: new ( ) , Applicability :: MachineApplicable )
3934
3942
} else {
3935
3943
( "..." . to_string ( ) , Applicability :: HasPlaceholders )
3936
3944
} ;
3937
3945
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 ;
3959
3974
}
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" ;
3970
3990
}
3991
+ Some ( hir:: def:: DefKind :: Ctor ( hir:: def:: CtorOf :: Struct , _) ) => {
3992
+ msg = "instantiate this tuple struct" ;
3993
+ }
3994
+ _ => { }
3971
3995
}
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
- _ => { }
3987
3996
}
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
+ }
3989
4013
if let Ok ( code) = self . sess ( ) . source_map ( ) . span_to_snippet ( expr. span ) {
3990
4014
err. span_suggestion (
3991
4015
expr. span ,
0 commit comments