Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 55d16b9

Browse files
committedNov 20, 2024·
Add shorter and more direct error for dyn AsyncFn
Fix #132713
1 parent 03ee484 commit 55d16b9

File tree

14 files changed

+291
-92
lines changed

14 files changed

+291
-92
lines changed
 

Diff for: ‎compiler/rustc_error_codes/src/error_codes/E0802.md

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
The `Async{Fn, FnMut, FnOnce}` traits are not yet `dyn`-compatible.
2+
3+
Erroneous code example:
4+
5+
```compile_fail,E0802
6+
async fn call_async_fn_twice(some_fn: &dyn AsyncFn()) {
7+
some_fn().await;
8+
some_fn().await;
9+
}
10+
```
11+
12+
One workaround to this issue is to use `impl Async...` instead:
13+
14+
```
15+
async fn call_async_fn_twice(some_fn: &impl AsyncFn()) {
16+
some_fn().await;
17+
some_fn().await;
18+
}
19+
```
20+
21+
This error indicates that you attempted to use `dyn AsyncFn`,
22+
`dyn AsyncFnMut`, or `dyn AsyncFnOnce`.
23+
24+
This is not yet possible because the `Async...` traits internally return
25+
a concrete `Future` associated type. For dynamic callsites, it is impossible
26+
to know the size of the returned `Future` object since different
27+
`Async...` implementations may return differently-sized `Future` objects.
28+
29+
This is analogous to the more general issue of creating a `dyn` type without
30+
specifying associated types, e.g. `dyn Iterator` as opposed to
31+
`dyn Iterator<Item = SomeItemType>`.

Diff for: ‎compiler/rustc_error_codes/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,7 @@ E0798: 0798,
541541
E0799: 0799,
542542
E0800: 0800,
543543
E0801: 0801,
544+
E0802: 0802,
544545
);
545546
)
546547
}

Diff for: ‎compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
103103
// most importantly, that the supertraits don't contain `Self`,
104104
// to avoid ICEs.
105105
for item in &regular_traits {
106-
let violations =
107-
hir_ty_lowering_dyn_compatibility_violations(tcx, item.trait_ref().def_id());
106+
let item_def_id = item.trait_ref().def_id();
107+
let violations = hir_ty_lowering_dyn_compatibility_violations(tcx, item_def_id);
108108
if !violations.is_empty() {
109-
let reported = report_dyn_incompatibility(
110-
tcx,
111-
span,
112-
Some(hir_id),
113-
item.trait_ref().def_id(),
114-
&violations,
115-
)
116-
.emit();
109+
let reported =
110+
report_dyn_incompatibility(tcx, span, Some(hir_id), item_def_id, &violations)
111+
.emit();
117112
return Ty::new_error(tcx, reported);
118113
}
119114
}

Diff for: ‎compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
733733
(span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect())
734734
})
735735
.collect();
736+
736737
let mut names: FxIndexMap<String, Vec<Symbol>> = Default::default();
737738
let mut names_len = 0;
738739

Diff for: ‎compiler/rustc_middle/src/traits/mod.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,22 @@ pub enum DynCompatibilityViolation {
712712

713713
/// GAT
714714
GAT(Symbol, Span),
715+
716+
/// Async{Fn, FnMut, FnOnce}
717+
///
718+
/// `fn_trait` is the name of the `AsyncFn...` trait,
719+
AsyncFnTrait {
720+
/// The `AsyncFn...` trait referenced.
721+
///
722+
/// This is useful for better error reporting in cases where the
723+
/// `dyn`-incompatible trait inherits from `Async...`.
724+
//
725+
// FIXME(cramertj): I'd love for this to be a DefId for proper comparison
726+
// in the error reporting stage, but sadly this isn't possible because
727+
// DefIds cannot be stored at this stage. Is there a better way to handle
728+
// catching the supertrait case than string comparison?
729+
fn_trait: Symbol,
730+
},
715731
}
716732

717733
impl DynCompatibilityViolation {
@@ -779,14 +795,18 @@ impl DynCompatibilityViolation {
779795
DynCompatibilityViolation::GAT(name, _) => {
780796
format!("it contains the generic associated type `{name}`").into()
781797
}
798+
DynCompatibilityViolation::AsyncFnTrait { .. } => {
799+
"`async` function traits are not yet `dyn`-compatible".into()
800+
}
782801
}
783802
}
784803

785804
pub fn solution(&self) -> DynCompatibilityViolationSolution {
786805
match self {
787806
DynCompatibilityViolation::SizedSelf(_)
788807
| DynCompatibilityViolation::SupertraitSelf(_)
789-
| DynCompatibilityViolation::SupertraitNonLifetimeBinder(..) => {
808+
| DynCompatibilityViolation::SupertraitNonLifetimeBinder(..)
809+
| DynCompatibilityViolation::AsyncFnTrait { .. } => {
790810
DynCompatibilityViolationSolution::None
791811
}
792812
DynCompatibilityViolation::Method(

Diff for: ‎compiler/rustc_middle/src/ty/context.rs

+4
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
560560
self.trait_is_alias(trait_def_id)
561561
}
562562

563+
fn trait_is_async_fn(self, trait_def_id: DefId) -> bool {
564+
self.trait_is_async_fn(trait_def_id)
565+
}
566+
563567
fn trait_is_dyn_compatible(self, trait_def_id: DefId) -> bool {
564568
self.is_dyn_compatible(trait_def_id)
565569
}

Diff for: ‎compiler/rustc_middle/src/ty/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1830,6 +1830,17 @@ impl<'tcx> TyCtxt<'tcx> {
18301830
self.trait_def(trait_def_id).has_auto_impl
18311831
}
18321832

1833+
/// Returns `true` if this is an `AsyncFn`, `AsyncFnMut`, or `AsyncFnOnce` trait.
1834+
pub fn trait_is_async_fn(self, trait_def_id: DefId) -> bool {
1835+
let lang_items = self.lang_items();
1836+
[
1837+
lang_items.async_fn_trait(),
1838+
lang_items.async_fn_mut_trait(),
1839+
lang_items.async_fn_once_trait(),
1840+
]
1841+
.contains(&Some(trait_def_id))
1842+
}
1843+
18331844
/// Returns `true` if this is coinductive, either because it is
18341845
/// an auto trait or because it has the `#[rustc_coinductive]` attribute.
18351846
pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool {

Diff for: ‎compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs

+64-20
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub mod suggestions;
77
use std::{fmt, iter};
88

99
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
10-
use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err};
10+
use rustc_errors::{Applicability, Diag, E0038, E0276, E0802, MultiSpan, struct_span_code_err};
1111
use rustc_hir::def_id::{DefId, LocalDefId};
1212
use rustc_hir::intravisit::Visitor;
1313
use rustc_hir::{self as hir, LangItem};
@@ -17,7 +17,7 @@ use rustc_infer::traits::{
1717
};
1818
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
1919
use rustc_middle::ty::{self, Ty, TyCtxt};
20-
use rustc_span::{ErrorGuaranteed, ExpnKind, Span};
20+
use rustc_span::{ErrorGuaranteed, ExpnKind, Span, Symbol};
2121
use tracing::{info, instrument};
2222

2323
pub use self::overflow::*;
@@ -428,10 +428,50 @@ pub fn report_dyn_incompatibility<'tcx>(
428428
violations: &[DynCompatibilityViolation],
429429
) -> Diag<'tcx> {
430430
let trait_str = tcx.def_path_str(trait_def_id);
431+
432+
// Avoid errors diving into the details of the `AsyncFn` traits if this is
433+
// a straightforward "`AsyncFn` is not yet `dyn`-compatible" error.
434+
if tcx.trait_is_async_fn(trait_def_id) {
435+
let fn_trait: Symbol = violations
436+
.iter()
437+
.find_map(|violation| {
438+
// Try to find the original trait that caused the violation.
439+
match *violation {
440+
DynCompatibilityViolation::AsyncFnTrait { fn_trait } => Some(fn_trait),
441+
_ => None,
442+
}
443+
})
444+
.expect("AsyncFn traits should report a corresponding DynCompatibilityViolation");
445+
let mut err = struct_span_code_err!(
446+
tcx.dcx(),
447+
span,
448+
E0802,
449+
"the trait `{}` is not yet `dyn`-compatible",
450+
fn_trait
451+
);
452+
// Note: this check is quite imprecise.
453+
// Comparing the DefIds or similar would be better, but we can't store
454+
// DefIds in `DynCompatibilityViolation`.
455+
if fn_trait.as_str() == trait_str {
456+
err.span_label(span, format!("`{fn_trait}` is not yet `dyn`-compatible"));
457+
} else {
458+
let trait_str = tcx.def_path_str(trait_def_id);
459+
err.span_label(
460+
span,
461+
format!(
462+
"`{trait_str}` inherits from `{fn_trait}` which is not yet `dyn`-compatible'"
463+
),
464+
);
465+
}
466+
attempt_dyn_to_impl_suggestion(tcx, hir_id, &mut err);
467+
return err;
468+
}
469+
431470
let trait_span = tcx.hir().get_if_local(trait_def_id).and_then(|node| match node {
432471
hir::Node::Item(item) => Some(item.ident.span),
433472
_ => None,
434473
});
474+
435475
let mut err = struct_span_code_err!(
436476
tcx.dcx(),
437477
span,
@@ -441,24 +481,8 @@ pub fn report_dyn_incompatibility<'tcx>(
441481
);
442482
err.span_label(span, format!("`{trait_str}` cannot be made into an object"));
443483

444-
if let Some(hir_id) = hir_id
445-
&& let hir::Node::Ty(ty) = tcx.hir_node(hir_id)
446-
&& let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind
447-
{
448-
let mut hir_id = hir_id;
449-
while let hir::Node::Ty(ty) = tcx.parent_hir_node(hir_id) {
450-
hir_id = ty.hir_id;
451-
}
452-
if tcx.parent_hir_node(hir_id).fn_sig().is_some() {
453-
// Do not suggest `impl Trait` when dealing with things like super-traits.
454-
err.span_suggestion_verbose(
455-
ty.span.until(trait_ref.span),
456-
"consider using an opaque type instead",
457-
"impl ",
458-
Applicability::MaybeIncorrect,
459-
);
460-
}
461-
}
484+
attempt_dyn_to_impl_suggestion(tcx, hir_id, &mut err);
485+
462486
let mut reported_violations = FxIndexSet::default();
463487
let mut multi_span = vec![];
464488
let mut messages = vec![];
@@ -583,3 +607,23 @@ pub fn report_dyn_incompatibility<'tcx>(
583607

584608
err
585609
}
610+
611+
fn attempt_dyn_to_impl_suggestion(tcx: TyCtxt<'_>, hir_id: Option<hir::HirId>, err: &mut Diag<'_>) {
612+
let Some(hir_id) = hir_id else { return };
613+
let hir::Node::Ty(ty) = tcx.hir_node(hir_id) else { return };
614+
let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind else { return };
615+
let mut hir_id = hir_id;
616+
while let hir::Node::Ty(ty) = tcx.parent_hir_node(hir_id) {
617+
hir_id = ty.hir_id;
618+
}
619+
if tcx.parent_hir_node(hir_id).fn_sig().is_none() {
620+
// Do not suggest `impl Trait` when dealing with things like super-traits.
621+
return;
622+
}
623+
err.span_suggestion_verbose(
624+
ty.span.until(trait_ref.span),
625+
"consider using an opaque type instead",
626+
"impl ",
627+
Applicability::MaybeIncorrect,
628+
);
629+
}

Diff for: ‎compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs

+21
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ pub fn hir_ty_lowering_dyn_compatibility_violations(
3939
trait_def_id: DefId,
4040
) -> Vec<DynCompatibilityViolation> {
4141
debug_assert!(tcx.generics_of(trait_def_id).has_self);
42+
43+
// Check for `AsyncFn` traits first to avoid reporting various other
44+
// errors about the details of why these traits aren't object-safe.
45+
for supertrait in tcx.supertrait_def_ids(trait_def_id) {
46+
if tcx.trait_is_async_fn(supertrait) {
47+
let fn_trait = tcx.item_name(supertrait);
48+
return vec![DynCompatibilityViolation::AsyncFnTrait { fn_trait }];
49+
}
50+
}
51+
4252
tcx.supertrait_def_ids(trait_def_id)
4353
.map(|def_id| predicates_reference_self(tcx, def_id, true))
4454
.filter(|spans| !spans.is_empty())
@@ -53,6 +63,17 @@ fn dyn_compatibility_violations(
5363
debug_assert!(tcx.generics_of(trait_def_id).has_self);
5464
debug!("dyn_compatibility_violations: {:?}", trait_def_id);
5565

66+
// Check for `AsyncFn` traits first to avoid reporting various other
67+
// errors about the details of why these traits aren't object-safe.
68+
for supertrait in tcx.supertrait_def_ids(trait_def_id) {
69+
if tcx.trait_is_async_fn(supertrait) {
70+
let fn_trait = tcx.item_name(supertrait);
71+
return core::slice::from_ref(
72+
tcx.arena.alloc(DynCompatibilityViolation::AsyncFnTrait { fn_trait }),
73+
);
74+
}
75+
}
76+
5677
tcx.arena.alloc_from_iter(
5778
tcx.supertrait_def_ids(trait_def_id)
5879
.flat_map(|def_id| dyn_compatibility_violations_for_trait(tcx, def_id)),

Diff for: ‎compiler/rustc_type_ir/src/interner.rs

+2
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ pub trait Interner:
262262

263263
fn trait_is_alias(self, trait_def_id: Self::DefId) -> bool;
264264

265+
fn trait_is_async_fn(self, trait_def_id: Self::DefId) -> bool;
266+
265267
fn trait_is_dyn_compatible(self, trait_def_id: Self::DefId) -> bool;
266268

267269
fn trait_is_fundamental(self, def_id: Self::DefId) -> bool;

Diff for: ‎tests/ui/async-await/async-closures/dyn.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Test the diagnostic output (error descriptions) resulting from `dyn AsyncFn{,Mut,Once}`.
2+
//@ edition:2018
3+
4+
#![feature(async_closure)]
5+
6+
use core::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce};
7+
8+
// --- Explicit `dyn` ---
9+
10+
fn takes_async_fn(_: &dyn AsyncFn()) {}
11+
//~^ ERROR the trait `AsyncFn` is not yet `dyn`-compatible
12+
13+
fn takes_async_fn_mut(_: &mut dyn AsyncFnMut()) {}
14+
//~^ ERROR the trait `AsyncFnMut` is not yet `dyn`-compatible
15+
16+
fn takes_async_fn_once(_: Box<dyn AsyncFnOnce()>) {}
17+
//~^ ERROR the trait `AsyncFnOnce` is not yet `dyn`-compatible
18+
19+
// --- Non-explicit `dyn` ---
20+
21+
#[allow(bare_trait_objects)]
22+
fn takes_async_fn_implicit_dyn(_: &AsyncFn()) {}
23+
//~^ ERROR the trait `AsyncFn` is not yet `dyn`-compatible
24+
25+
#[allow(bare_trait_objects)]
26+
fn takes_async_fn_mut_implicit_dyn(_: &mut AsyncFnMut()) {}
27+
//~^ ERROR the trait `AsyncFnMut` is not yet `dyn`-compatible
28+
29+
#[allow(bare_trait_objects)]
30+
fn takes_async_fn_once_implicit_dyn(_: Box<AsyncFnOnce()>) {}
31+
//~^ ERROR the trait `AsyncFnOnce` is not yet `dyn`-compatible
32+
33+
// --- Supertrait ---
34+
35+
trait SubAsyncFn: AsyncFn() {}
36+
fn takes_sub_async_fn(_: &dyn SubAsyncFn) {}
37+
//~^ ERROR the trait `SubAsyncFn` cannot be made into an object
38+
39+
fn main() {}

Diff for: ‎tests/ui/async-await/async-closures/dyn.stderr

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
error[E0802]: the trait `AsyncFn` is not yet `dyn`-compatible
2+
--> $DIR/dyn.rs:10:23
3+
|
4+
LL | fn takes_async_fn(_: &dyn AsyncFn()) {}
5+
| ^^^^^^^^^^^^^ `AsyncFn` is not yet `dyn`-compatible
6+
|
7+
help: consider using an opaque type instead
8+
|
9+
LL | fn takes_async_fn(_: &impl AsyncFn()) {}
10+
| ~~~~
11+
12+
error[E0802]: the trait `AsyncFnMut` is not yet `dyn`-compatible
13+
--> $DIR/dyn.rs:13:31
14+
|
15+
LL | fn takes_async_fn_mut(_: &mut dyn AsyncFnMut()) {}
16+
| ^^^^^^^^^^^^^^^^ `AsyncFnMut` is not yet `dyn`-compatible
17+
|
18+
help: consider using an opaque type instead
19+
|
20+
LL | fn takes_async_fn_mut(_: &mut impl AsyncFnMut()) {}
21+
| ~~~~
22+
23+
error[E0802]: the trait `AsyncFnOnce` is not yet `dyn`-compatible
24+
--> $DIR/dyn.rs:16:31
25+
|
26+
LL | fn takes_async_fn_once(_: Box<dyn AsyncFnOnce()>) {}
27+
| ^^^^^^^^^^^^^^^^^ `AsyncFnOnce` is not yet `dyn`-compatible
28+
|
29+
help: consider using an opaque type instead
30+
|
31+
LL | fn takes_async_fn_once(_: Box<impl AsyncFnOnce()>) {}
32+
| ~~~~
33+
34+
error[E0802]: the trait `AsyncFn` is not yet `dyn`-compatible
35+
--> $DIR/dyn.rs:22:36
36+
|
37+
LL | fn takes_async_fn_implicit_dyn(_: &AsyncFn()) {}
38+
| ^^^^^^^^^ `AsyncFn` is not yet `dyn`-compatible
39+
|
40+
help: consider using an opaque type instead
41+
|
42+
LL | fn takes_async_fn_implicit_dyn(_: &impl AsyncFn()) {}
43+
| ++++
44+
45+
error[E0802]: the trait `AsyncFnMut` is not yet `dyn`-compatible
46+
--> $DIR/dyn.rs:26:44
47+
|
48+
LL | fn takes_async_fn_mut_implicit_dyn(_: &mut AsyncFnMut()) {}
49+
| ^^^^^^^^^^^^ `AsyncFnMut` is not yet `dyn`-compatible
50+
|
51+
help: consider using an opaque type instead
52+
|
53+
LL | fn takes_async_fn_mut_implicit_dyn(_: &mut impl AsyncFnMut()) {}
54+
| ++++
55+
56+
error[E0802]: the trait `AsyncFnOnce` is not yet `dyn`-compatible
57+
--> $DIR/dyn.rs:30:44
58+
|
59+
LL | fn takes_async_fn_once_implicit_dyn(_: Box<AsyncFnOnce()>) {}
60+
| ^^^^^^^^^^^^^ `AsyncFnOnce` is not yet `dyn`-compatible
61+
|
62+
help: consider using an opaque type instead
63+
|
64+
LL | fn takes_async_fn_once_implicit_dyn(_: Box<impl AsyncFnOnce()>) {}
65+
| ++++
66+
67+
error[E0038]: the trait `SubAsyncFn` cannot be made into an object
68+
--> $DIR/dyn.rs:36:27
69+
|
70+
LL | fn takes_sub_async_fn(_: &dyn SubAsyncFn) {}
71+
| ^^^^^^^^^^^^^^ `SubAsyncFn` cannot be made into an object
72+
|
73+
= note: the trait cannot be made into an object because `async` function traits are not yet `dyn`-compatible
74+
= note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
75+
help: consider using an opaque type instead
76+
|
77+
LL | fn takes_sub_async_fn(_: &impl SubAsyncFn) {}
78+
| ~~~~
79+
80+
error: aborting due to 7 previous errors
81+
82+
Some errors have detailed explanations: E0038, E0802.
83+
For more information about an error, try `rustc --explain E0038`.

Diff for: ‎tests/ui/async-await/async-fn/dyn-pos.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
#![feature(async_closure)]
44

55
fn foo(x: &dyn async Fn()) {}
6-
//~^ ERROR the trait `AsyncFn` cannot be made into an object
7-
//~| ERROR the trait `AsyncFnMut` cannot be made into an object
8-
//~| ERROR the trait `AsyncFnMut` cannot be made into an object
9-
//~| ERROR the trait `AsyncFnMut` cannot be made into an object
6+
//~^ ERROR the trait `AsyncFn` is not yet `dyn`-compatible
107

118
fn main() {}

Diff for: ‎tests/ui/async-await/async-fn/dyn-pos.stderr

+7-57
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,14 @@
1-
error[E0038]: the trait `AsyncFnMut` cannot be made into an object
2-
--> $DIR/dyn-pos.rs:5:16
3-
|
4-
LL | fn foo(x: &dyn async Fn()) {}
5-
| ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object
6-
|
7-
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
8-
--> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
9-
|
10-
= note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture`
11-
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFnMut` for this new enum and using it instead:
12-
&F
13-
&mut F
14-
std::boxed::Box<F, A>
15-
16-
error[E0038]: the trait `AsyncFnMut` cannot be made into an object
17-
--> $DIR/dyn-pos.rs:5:16
18-
|
19-
LL | fn foo(x: &dyn async Fn()) {}
20-
| ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object
21-
|
22-
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
23-
--> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
24-
|
25-
= note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture`
26-
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFnMut` for this new enum and using it instead:
27-
&F
28-
&mut F
29-
std::boxed::Box<F, A>
30-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
31-
32-
error[E0038]: the trait `AsyncFnMut` cannot be made into an object
33-
--> $DIR/dyn-pos.rs:5:16
34-
|
35-
LL | fn foo(x: &dyn async Fn()) {}
36-
| ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object
37-
|
38-
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
39-
--> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
40-
|
41-
= note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture`
42-
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFnMut` for this new enum and using it instead:
43-
&F
44-
&mut F
45-
std::boxed::Box<F, A>
46-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
47-
48-
error[E0038]: the trait `AsyncFn` cannot be made into an object
1+
error[E0802]: the trait `AsyncFn` is not yet `dyn`-compatible
492
--> $DIR/dyn-pos.rs:5:12
503
|
514
LL | fn foo(x: &dyn async Fn()) {}
52-
| ^^^^^^^^^^^^^^ `AsyncFn` cannot be made into an object
5+
| ^^^^^^^^^^^^^^ `AsyncFn` is not yet `dyn`-compatible
536
|
54-
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
55-
--> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
7+
help: consider using an opaque type instead
568
|
57-
= note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture`
58-
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFn` for this new enum and using it instead:
59-
&F
60-
std::boxed::Box<F, A>
9+
LL | fn foo(x: &impl async Fn()) {}
10+
| ~~~~
6111

62-
error: aborting due to 4 previous errors
12+
error: aborting due to 1 previous error
6313

64-
For more information about this error, try `rustc --explain E0038`.
14+
For more information about this error, try `rustc --explain E0802`.

0 commit comments

Comments
 (0)
Please sign in to comment.