Skip to content

Commit d617f18

Browse files
Pretty print AsyncFn traits too
1 parent e47c47d commit d617f18

File tree

6 files changed

+70
-14
lines changed

6 files changed

+70
-14
lines changed

compiler/rustc_middle/src/middle/lang_items.rs

+11
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ impl<'tcx> TyCtxt<'tcx> {
6868
}
6969
}
7070

71+
/// Given a [`ty::ClosureKind`], get the [`DefId`] of its corresponding `Fn`-family
72+
/// trait, if it is defined.
73+
pub fn async_fn_trait_kind_to_def_id(self, kind: ty::ClosureKind) -> Option<DefId> {
74+
let items = self.lang_items();
75+
match kind {
76+
ty::ClosureKind::Fn => items.async_fn_trait(),
77+
ty::ClosureKind::FnMut => items.async_fn_mut_trait(),
78+
ty::ClosureKind::FnOnce => items.async_fn_once_trait(),
79+
}
80+
}
81+
7182
/// Returns `true` if `id` is a `DefId` of [`Fn`], [`FnMut`] or [`FnOnce`] traits.
7283
pub fn is_fn_trait(self, id: DefId) -> bool {
7384
self.fn_trait_kind_from_def_id(id).is_some()

compiler/rustc_middle/src/ty/print/pretty.rs

+22-8
Original file line numberDiff line numberDiff line change
@@ -1040,12 +1040,15 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
10401040
// Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait
10411041
let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !has_sized_bound;
10421042

1043-
for (bound_args, entry) in fn_traits {
1043+
for ((bound_args, is_async), entry) in fn_traits {
10441044
write!(self, "{}", if first { "" } else { " + " })?;
10451045
write!(self, "{}", if paren_needed { "(" } else { "" })?;
10461046

1047-
let trait_def_id =
1048-
tcx.fn_trait_kind_to_def_id(entry.kind).expect("expected Fn lang items");
1047+
let trait_def_id = if is_async {
1048+
tcx.async_fn_trait_kind_to_def_id(entry.kind).expect("expected AsyncFn lang items")
1049+
} else {
1050+
tcx.fn_trait_kind_to_def_id(entry.kind).expect("expected Fn lang items")
1051+
};
10491052

10501053
if let Some(return_ty) = entry.return_ty {
10511054
self.wrap_binder(&bound_args, |args, cx| {
@@ -1209,17 +1212,28 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
12091212
ty::PolyTraitPredicate<'tcx>,
12101213
FxIndexMap<DefId, ty::Binder<'tcx, Term<'tcx>>>,
12111214
>,
1212-
fn_traits: &mut FxIndexMap<ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>>, OpaqueFnEntry<'tcx>>,
1215+
fn_traits: &mut FxIndexMap<
1216+
(ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>>, bool),
1217+
OpaqueFnEntry<'tcx>,
1218+
>,
12131219
) {
12141220
let tcx = self.tcx();
12151221
let trait_def_id = trait_pred.def_id();
12161222

1223+
let fn_trait_and_async = if let Some(kind) = tcx.fn_trait_kind_from_def_id(trait_def_id) {
1224+
Some((kind, false))
1225+
} else if let Some(kind) = tcx.async_fn_trait_kind_from_def_id(trait_def_id) {
1226+
Some((kind, true))
1227+
} else {
1228+
None
1229+
};
1230+
12171231
if trait_pred.polarity() == ty::PredicatePolarity::Positive
1218-
&& let Some(kind) = tcx.fn_trait_kind_from_def_id(trait_def_id)
1232+
&& let Some((kind, is_async)) = fn_trait_and_async
12191233
&& let ty::Tuple(types) = *trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
12201234
{
12211235
let entry = fn_traits
1222-
.entry(trait_pred.rebind(types))
1236+
.entry((trait_pred.rebind(types), is_async))
12231237
.or_insert_with(|| OpaqueFnEntry { kind, return_ty: None });
12241238
if kind.extends(entry.kind) {
12251239
entry.kind = kind;
@@ -3148,10 +3162,10 @@ define_print_and_forward_display! {
31483162

31493163
TraitRefPrintSugared<'tcx> {
31503164
if !with_reduced_queries()
3151-
&& let Some(kind) = cx.tcx().fn_trait_kind_from_def_id(self.0.def_id)
3165+
&& cx.tcx().trait_def(self.0.def_id).paren_sugar
31523166
&& let ty::Tuple(args) = self.0.args.type_at(1).kind()
31533167
{
3154-
p!(write("{}", kind.as_str()), "(");
3168+
p!(write("{}", cx.tcx().item_name(self.0.def_id)), "(");
31553169
for (i, arg) in args.iter().enumerate() {
31563170
if i > 0 {
31573171
p!(", ");

tests/ui/async-await/async-closures/fn-exception-target-features.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0277]: the trait bound `fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}: AsyncFn<()>` is not satisfied
1+
error[E0277]: the trait bound `fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}: AsyncFn()` is not satisfied
22
--> $DIR/fn-exception-target-features.rs:16:10
33
|
44
LL | test(target_feature);
5-
| ---- ^^^^^^^^^^^^^^ the trait `AsyncFn<()>` is not implemented for fn item `fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}`
5+
| ---- ^^^^^^^^^^^^^^ the trait `AsyncFn()` is not implemented for fn item `fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}`
66
| |
77
| required by a bound introduced by this call
88
|

tests/ui/async-await/async-closures/fn-exception.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0277]: the trait bound `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}: AsyncFn<()>` is not satisfied
1+
error[E0277]: the trait bound `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}: AsyncFn()` is not satisfied
22
--> $DIR/fn-exception.rs:19:10
33
|
44
LL | test(unsafety);
5-
| ---- ^^^^^^^^ the trait `AsyncFn<()>` is not implemented for fn item `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}`
5+
| ---- ^^^^^^^^ the trait `AsyncFn()` is not implemented for fn item `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}`
66
| |
77
| required by a bound introduced by this call
88
|
@@ -12,11 +12,11 @@ note: required by a bound in `test`
1212
LL | fn test(f: impl async Fn()) {}
1313
| ^^^^^^^^^^ required by this bound in `test`
1414

15-
error[E0277]: the trait bound `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}: AsyncFn<()>` is not satisfied
15+
error[E0277]: the trait bound `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}: AsyncFn()` is not satisfied
1616
--> $DIR/fn-exception.rs:20:10
1717
|
1818
LL | test(abi);
19-
| ---- ^^^ the trait `AsyncFn<()>` is not implemented for fn item `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}`
19+
| ---- ^^^ the trait `AsyncFn()` is not implemented for fn item `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}`
2020
| |
2121
| required by a bound introduced by this call
2222
|
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ edition: 2021
2+
3+
#![feature(async_closure)]
4+
5+
use std::ops::AsyncFnMut;
6+
7+
fn produce() -> impl AsyncFnMut() -> &'static str {
8+
async || ""
9+
}
10+
11+
fn main() {
12+
let x: i32 = produce();
13+
//~^ ERROR mismatched types
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/pretty-async-fn-opaque.rs:12:18
3+
|
4+
LL | fn produce() -> impl AsyncFnMut() -> &'static str {
5+
| --------------------------------- the found opaque type
6+
...
7+
LL | let x: i32 = produce();
8+
| --- ^^^^^^^^^ expected `i32`, found opaque type
9+
| |
10+
| expected due to this
11+
|
12+
= note: expected type `i32`
13+
found opaque type `impl AsyncFnMut() -> &'static str`
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)