Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (expected_sig, expected_kind) = match expected.to_option(self) {
Some(ty) => self.deduce_closure_signature(
self.deeply_resolve_ignoring_regions_with_obligations(ty),
closure.def_id,
closure.kind,
),
None => (None, None),
Expand Down Expand Up @@ -291,9 +292,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn deduce_closure_signature(
&self,
expected_ty: Ty<'tcx>,
closure_def_id: LocalDefId,
closure_kind: hir::ClosureKind,
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
match *expected_ty.kind() {
ty::Coroutine(def_id, args)
if def_id == closure_def_id.to_def_id()
&& matches!(
closure_kind,
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
hir::CoroutineSource::Closure,
))
) =>
{
// An async closure's body is itself a coroutine. Propagate the signature
// inferred for that coroutine into its body.
let args = args.as_coroutine();
let sig = ty::Binder::dummy(
self.tcx.mk_fn_sig_safe_rust_abi([args.resume_ty()], args.return_ty()),
);
(Some(ExpectedSig { cause_span: None, sig }), None)
}
ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => self
.deduce_closure_signature_from_predicates(
expected_ty,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0308]: mismatched types
--> $DIR/async-closure-output-mismatch-issue-161619.rs:16:27
|
LL | for_each(async |_| Ok(String::new()));
| -- ^^^^^^^^^^^^^ expected `()`, found `String`
| |
| arguments to this enum variant are incorrect
|
help: the type constructed contains `String` due to the type of the argument passed
--> $DIR/async-closure-output-mismatch-issue-161619.rs:16:24
|
LL | for_each(async |_| Ok(String::new()));
| ^^^-------------^
| |
| this argument influences the type of `Ok`
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0308]: mismatched types
--> $DIR/async-closure-output-mismatch-issue-161619.rs:16:27
|
LL | for_each(async |_| Ok(String::new()));
| -- ^^^^^^^^^^^^^ expected `()`, found `String`
| |
| arguments to this enum variant are incorrect
|
help: the type constructed contains `String` due to the type of the argument passed
--> $DIR/async-closure-output-mismatch-issue-161619.rs:16:24
|
LL | for_each(async |_| Ok(String::new()));
| ^^^-------------^
| |
| this argument influences the type of `Ok`
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//@ edition: 2024
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver

use std::future::Future;

fn for_each<F, Fut>(_: F)
where
F: FnMut(()) -> Fut,
Fut: Future<Output = Result<(), ()>>,
{
}

fn main() {
for_each(async |_| Ok(String::new()));
//~^ ERROR mismatched types
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ fn f(_c: impl Future<Output = ()>) {}

fn main() {
f((async || {})()); //~ ERROR: expected function, found `()`
//~^ ERROR: is not a future
f(async {});
//~^ ERROR: is not a future
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ fn f(_c: impl Future<Output = ()>) {}

fn main() {
f(async || {}()); //~ ERROR: expected function, found `()`
//~^ ERROR: is not a future
f(async || {});
//~^ ERROR: is not a future
}
25 changes: 5 additions & 20 deletions tests/ui/suggestions/suggest-create-closure-issue-150701.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,15 @@ help: if you meant to create this closure and immediately call it, surround the
LL | f((async || {})());
| + +

error[E0277]: `{async closure@$DIR/suggest-create-closure-issue-150701.rs:11:7: 11:15}` is not a future
--> $DIR/suggest-create-closure-issue-150701.rs:11:7
|
LL | f(async || {}());
| - ^^^^^^^^^^^^^ `{async closure@$DIR/suggest-create-closure-issue-150701.rs:11:7: 11:15}` is not a future
| |
| required by a bound introduced by this call
|
= help: the trait `Future` is not implemented for `{async closure@$DIR/suggest-create-closure-issue-150701.rs:11:7: 11:15}`
note: required by a bound in `f`
--> $DIR/suggest-create-closure-issue-150701.rs:8:15
|
LL | fn f(_c: impl Future<Output = ()>) {}
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `f`

error[E0277]: `{async closure@$DIR/suggest-create-closure-issue-150701.rs:13:7: 13:15}` is not a future
--> $DIR/suggest-create-closure-issue-150701.rs:13:7
error[E0277]: `{async closure@$DIR/suggest-create-closure-issue-150701.rs:12:7: 12:15}` is not a future
--> $DIR/suggest-create-closure-issue-150701.rs:12:7
|
LL | f(async || {});
| - ^^^^^^^^^^^ `{async closure@$DIR/suggest-create-closure-issue-150701.rs:13:7: 13:15}` is not a future
| - ^^^^^^^^^^^ `{async closure@$DIR/suggest-create-closure-issue-150701.rs:12:7: 12:15}` is not a future
| |
| required by a bound introduced by this call
|
= help: the trait `Future` is not implemented for `{async closure@$DIR/suggest-create-closure-issue-150701.rs:13:7: 13:15}`
= help: the trait `Future` is not implemented for `{async closure@$DIR/suggest-create-closure-issue-150701.rs:12:7: 12:15}`
note: required by a bound in `f`
--> $DIR/suggest-create-closure-issue-150701.rs:8:15
|
Expand All @@ -46,7 +31,7 @@ LL - f(async || {});
LL + f(async {});
|

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

Some errors have detailed explanations: E0277, E0618.
For more information about an error, try `rustc --explain E0277`.
Loading