Improve error message for AsyncFn trait failure for RPIT · rust-lang/rust@e213f4b (original) (raw)
`@@ -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
``