Skip to content

Commit

Permalink
Suggest correct signature on missing fn returning RPITIT/AFIT
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Jun 13, 2023
1 parent 2ca8d35 commit dbee24d
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 2 deletions.
31 changes: 29 additions & 2 deletions compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,32 @@ fn fn_sig_suggestion<'tcx>(
.flatten()
.collect::<Vec<String>>()
.join(", ");
let output = sig.output();
let mut output = sig.output();

let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
output = if let ty::Alias(_, alias_ty) = *output.kind() {
tcx.explicit_item_bounds(alias_ty.def_id)
.subst_iter_copied(tcx, alias_ty.substs)
.find_map(|(bound, _)| {
bound.to_opt_poly_projection_pred()?.no_bound_vars()?.term.ty()
})
.unwrap_or_else(|| {
span_bug!(
ident.span,
"expected async fn to have `impl Future` output, but it returns {output}"
)
})
} else {
span_bug!(
ident.span,
"expected async fn to have `impl Future` output, but it returns {output}"
)
};
"async "
} else {
""
};

let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() };

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

pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
Expand Down
22 changes: 22 additions & 0 deletions tests/ui/impl-trait/in-trait/suggest-missing-item.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// edition:2021
// run-rustfix

#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]

trait Trait {
async fn foo();

async fn bar() -> i32;

fn test(&self) -> impl Sized + '_;
}

struct S;

impl Trait for S {fn test(&self) -> impl Sized + '_ { todo!() }
async fn bar() -> i32 { todo!() }
async fn foo() { todo!() }
}
//~^ ERROR not all trait items implemented

fn main() {}
19 changes: 19 additions & 0 deletions tests/ui/impl-trait/in-trait/suggest-missing-item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// edition:2021
// run-rustfix

#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]

trait Trait {
async fn foo();

async fn bar() -> i32;

fn test(&self) -> impl Sized + '_;
}

struct S;

impl Trait for S {}
//~^ ERROR not all trait items implemented

fn main() {}
18 changes: 18 additions & 0 deletions tests/ui/impl-trait/in-trait/suggest-missing-item.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `test`
--> $DIR/suggest-missing-item.rs:16:1
|
LL | async fn foo();
| --------------- `foo` from trait
LL |
LL | async fn bar() -> i32;
| ---------------------- `bar` from trait
LL |
LL | fn test(&self) -> impl Sized + '_;
| ---------------------------------- `test` from trait
...
LL | impl Trait for S {}
| ^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `test` in implementation

error: aborting due to previous error

For more information about this error, try `rustc --explain E0046`.

0 comments on commit dbee24d

Please sign in to comment.