Skip to content

Commit dbee24d

Browse files
committedJun 13, 2023
Suggest correct signature on missing fn returning RPITIT/AFIT
1 parent 2ca8d35 commit dbee24d

File tree

4 files changed

+88
-2
lines changed

4 files changed

+88
-2
lines changed
 

Diff for: ‎compiler/rustc_hir_analysis/src/check/mod.rs

+29-2
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,32 @@ fn fn_sig_suggestion<'tcx>(
403403
.flatten()
404404
.collect::<Vec<String>>()
405405
.join(", ");
406-
let output = sig.output();
406+
let mut output = sig.output();
407+
408+
let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
409+
output = if let ty::Alias(_, alias_ty) = *output.kind() {
410+
tcx.explicit_item_bounds(alias_ty.def_id)
411+
.subst_iter_copied(tcx, alias_ty.substs)
412+
.find_map(|(bound, _)| {
413+
bound.to_opt_poly_projection_pred()?.no_bound_vars()?.term.ty()
414+
})
415+
.unwrap_or_else(|| {
416+
span_bug!(
417+
ident.span,
418+
"expected async fn to have `impl Future` output, but it returns {output}"
419+
)
420+
})
421+
} else {
422+
span_bug!(
423+
ident.span,
424+
"expected async fn to have `impl Future` output, but it returns {output}"
425+
)
426+
};
427+
"async "
428+
} else {
429+
""
430+
};
431+
407432
let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() };
408433

409434
let unsafety = sig.unsafety.prefix_str();
@@ -414,7 +439,9 @@ fn fn_sig_suggestion<'tcx>(
414439
// lifetimes between the `impl` and the `trait`, but this should be good enough to
415440
// fill in a significant portion of the missing code, and other subsequent
416441
// suggestions can help the user fix the code.
417-
format!("{unsafety}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}")
442+
format!(
443+
"{unsafety}{asyncness}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}"
444+
)
418445
}
419446

420447
pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// edition:2021
2+
// run-rustfix
3+
4+
#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
5+
6+
trait Trait {
7+
async fn foo();
8+
9+
async fn bar() -> i32;
10+
11+
fn test(&self) -> impl Sized + '_;
12+
}
13+
14+
struct S;
15+
16+
impl Trait for S {fn test(&self) -> impl Sized + '_ { todo!() }
17+
async fn bar() -> i32 { todo!() }
18+
async fn foo() { todo!() }
19+
}
20+
//~^ ERROR not all trait items implemented
21+
22+
fn main() {}

Diff for: ‎tests/ui/impl-trait/in-trait/suggest-missing-item.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// edition:2021
2+
// run-rustfix
3+
4+
#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
5+
6+
trait Trait {
7+
async fn foo();
8+
9+
async fn bar() -> i32;
10+
11+
fn test(&self) -> impl Sized + '_;
12+
}
13+
14+
struct S;
15+
16+
impl Trait for S {}
17+
//~^ ERROR not all trait items implemented
18+
19+
fn main() {}
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `test`
2+
--> $DIR/suggest-missing-item.rs:16:1
3+
|
4+
LL | async fn foo();
5+
| --------------- `foo` from trait
6+
LL |
7+
LL | async fn bar() -> i32;
8+
| ---------------------- `bar` from trait
9+
LL |
10+
LL | fn test(&self) -> impl Sized + '_;
11+
| ---------------------------------- `test` from trait
12+
...
13+
LL | impl Trait for S {}
14+
| ^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `test` in implementation
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0046`.

0 commit comments

Comments
 (0)
Please sign in to comment.