@@ -829,7 +829,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
829
829
&& let ty:: Closure ( closure_def_id, _) | ty:: CoroutineClosure ( closure_def_id, _) =
830
830
* typeck_results. node_type ( arg_hir_id) . kind ( )
831
831
{
832
- // Otherwise, extract the closure kind from the obligation.
832
+ // Otherwise, extract the closure kind from the obligation,
833
+ // but only if we actually have an argument to deduce the
834
+ // closure type from...
833
835
let mut err = self . report_closure_error (
834
836
& obligation,
835
837
closure_def_id,
@@ -844,63 +846,72 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
844
846
845
847
let self_ty = trait_pred. self_ty ( ) . skip_binder ( ) ;
846
848
847
- if let Some ( expected_kind) = self . tcx . fn_trait_kind_from_def_id ( trait_pred. def_id ( ) ) {
848
- let ( closure_def_id, found_args, by_ref_captures) = match * self_ty. kind ( ) {
849
- ty:: Closure ( def_id, args) => {
850
- ( def_id, args. as_closure ( ) . sig ( ) . map_bound ( |sig| sig. inputs ( ) [ 0 ] ) , None )
851
- }
852
- ty:: CoroutineClosure ( def_id, args) => (
853
- def_id,
854
- args. as_coroutine_closure ( )
855
- . coroutine_closure_sig ( )
856
- . map_bound ( |sig| sig. tupled_inputs_ty ) ,
857
- Some ( args. as_coroutine_closure ( ) . coroutine_captures_by_ref_ty ( ) ) ,
858
- ) ,
859
- _ => return None ,
849
+ let ( expected_kind, trait_prefix) =
850
+ if let Some ( expected_kind) = self . tcx . fn_trait_kind_from_def_id ( trait_pred. def_id ( ) ) {
851
+ ( expected_kind, "" )
852
+ } else if let Some ( expected_kind) =
853
+ self . tcx . async_fn_trait_kind_from_def_id ( trait_pred. def_id ( ) )
854
+ {
855
+ ( expected_kind, "Async" )
856
+ } else {
857
+ return None ;
860
858
} ;
861
859
862
- let expected_args =
863
- trait_pred. map_bound ( |trait_pred| trait_pred. trait_ref . args . type_at ( 1 ) ) ;
864
-
865
- // Verify that the arguments are compatible. If the signature is
866
- // mismatched, then we have a totally different error to report.
867
- if self . enter_forall ( found_args, |found_args| {
868
- self . enter_forall ( expected_args, |expected_args| {
869
- !self . can_eq ( obligation. param_env , expected_args, found_args)
870
- } )
871
- } ) {
872
- return None ;
860
+ let ( closure_def_id, found_args, by_ref_captures) = match * self_ty. kind ( ) {
861
+ ty:: Closure ( def_id, args) => {
862
+ ( def_id, args. as_closure ( ) . sig ( ) . map_bound ( |sig| sig. inputs ( ) [ 0 ] ) , None )
873
863
}
864
+ ty:: CoroutineClosure ( def_id, args) => (
865
+ def_id,
866
+ args. as_coroutine_closure ( )
867
+ . coroutine_closure_sig ( )
868
+ . map_bound ( |sig| sig. tupled_inputs_ty ) ,
869
+ Some ( args. as_coroutine_closure ( ) . coroutine_captures_by_ref_ty ( ) ) ,
870
+ ) ,
871
+ _ => return None ,
872
+ } ;
874
873
875
- if let Some ( found_kind) = self . closure_kind ( self_ty)
876
- && !found_kind. extends ( expected_kind)
877
- {
878
- let mut err = self . report_closure_error (
879
- & obligation,
880
- closure_def_id,
881
- found_kind,
882
- expected_kind,
883
- "" ,
884
- ) ;
885
- self . note_obligation_cause ( & mut err, & obligation) ;
886
- return Some ( err. emit ( ) ) ;
887
- }
874
+ let expected_args = trait_pred. map_bound ( |trait_pred| trait_pred. trait_ref . args . type_at ( 1 ) ) ;
888
875
889
- // If the closure has captures, then perhaps the reason that the trait
890
- // is unimplemented is because async closures don't implement `Fn`/`FnMut`
891
- // if they have captures.
892
- if let Some ( by_ref_captures) = by_ref_captures
893
- && let ty:: FnPtr ( sig_tys, _) = by_ref_captures. kind ( )
894
- && !sig_tys. skip_binder ( ) . output ( ) . is_unit ( )
895
- {
896
- let mut err = self . dcx ( ) . create_err ( AsyncClosureNotFn {
897
- span : self . tcx . def_span ( closure_def_id) ,
898
- kind : expected_kind. as_str ( ) ,
899
- } ) ;
900
- self . note_obligation_cause ( & mut err, & obligation) ;
901
- return Some ( err. emit ( ) ) ;
902
- }
876
+ // Verify that the arguments are compatible. If the signature is
877
+ // mismatched, then we have a totally different error to report.
878
+ if self . enter_forall ( found_args, |found_args| {
879
+ self . enter_forall ( expected_args, |expected_args| {
880
+ !self . can_eq ( obligation. param_env , expected_args, found_args)
881
+ } )
882
+ } ) {
883
+ return None ;
903
884
}
885
+
886
+ if let Some ( found_kind) = self . closure_kind ( self_ty)
887
+ && !found_kind. extends ( expected_kind)
888
+ {
889
+ let mut err = self . report_closure_error (
890
+ & obligation,
891
+ closure_def_id,
892
+ found_kind,
893
+ expected_kind,
894
+ trait_prefix,
895
+ ) ;
896
+ self . note_obligation_cause ( & mut err, & obligation) ;
897
+ return Some ( err. emit ( ) ) ;
898
+ }
899
+
900
+ // If the closure has captures, then perhaps the reason that the trait
901
+ // is unimplemented is because async closures don't implement `Fn`/`FnMut`
902
+ // if they have captures.
903
+ if let Some ( by_ref_captures) = by_ref_captures
904
+ && let ty:: FnPtr ( sig_tys, _) = by_ref_captures. kind ( )
905
+ && !sig_tys. skip_binder ( ) . output ( ) . is_unit ( )
906
+ {
907
+ let mut err = self . dcx ( ) . create_err ( AsyncClosureNotFn {
908
+ span : self . tcx . def_span ( closure_def_id) ,
909
+ kind : expected_kind. as_str ( ) ,
910
+ } ) ;
911
+ self . note_obligation_cause ( & mut err, & obligation) ;
912
+ return Some ( err. emit ( ) ) ;
913
+ }
914
+
904
915
None
905
916
}
906
917
0 commit comments