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

``