@@ -829,7 +829,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
829829 && let ty:: Closure ( closure_def_id, _) | ty:: CoroutineClosure ( closure_def_id, _) =
830830 * typeck_results. node_type ( arg_hir_id) . kind ( )
831831 {
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...
833835 let mut err = self . report_closure_error (
834836 & obligation,
835837 closure_def_id,
@@ -844,63 +846,72 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
844846
845847 let self_ty = trait_pred. self_ty ( ) . skip_binder ( ) ;
846848
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 ;
860858 } ;
861859
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 )
873863 }
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+ } ;
874873
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 ) ) ;
888875
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 ;
903884 }
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+
904915 None
905916 }
906917
0 commit comments