Skip to content

Commit 6bad3ee

Browse files
authored
Rollup merge of rust-lang#70679 - tmandry:issue-68112, r=nikomatsakis
Improve async-await/generator obligation errors in some cases Fixes rust-lang#68112. This change is best read one commit at a time (I add a test at the beginning and update it in each change after). The `test2` function is a case I found while writing the test that we don't handle with this code yet. I don't attempt to fix it in this PR, but it's a good candidate for future work. r? @davidtwco, @nikomatsakis
2 parents 8f98e5d + 889cfe1 commit 6bad3ee

18 files changed

+411
-106
lines changed

src/librustc_ast_lowering/expr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
590590
await_span,
591591
self.allow_gen_future.clone(),
592592
);
593+
let expr = self.lower_expr(expr);
593594

594595
let pinned_ident = Ident::with_dummy_span(sym::pinned);
595596
let (pinned_pat, pinned_pat_hid) =
@@ -671,7 +672,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
671672
let unit = self.expr_unit(span);
672673
let yield_expr = self.expr(
673674
span,
674-
hir::ExprKind::Yield(unit, hir::YieldSource::Await),
675+
hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr.hir_id) }),
675676
ThinVec::new(),
676677
);
677678
let yield_expr = self.arena.alloc(yield_expr);
@@ -704,7 +705,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
704705
// match <expr> {
705706
// mut pinned => loop { .. }
706707
// }
707-
let expr = self.lower_expr(expr);
708708
hir::ExprKind::Match(expr, arena_vec![self; pinned_arm], hir::MatchSource::AwaitDesugar)
709709
}
710710

src/librustc_hir/hir.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,15 +1736,24 @@ pub struct Destination {
17361736
#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
17371737
pub enum YieldSource {
17381738
/// An `<expr>.await`.
1739-
Await,
1739+
Await { expr: Option<HirId> },
17401740
/// A plain `yield`.
17411741
Yield,
17421742
}
17431743

1744+
impl YieldSource {
1745+
pub fn is_await(&self) -> bool {
1746+
match self {
1747+
YieldSource::Await { .. } => true,
1748+
YieldSource::Yield => false,
1749+
}
1750+
}
1751+
}
1752+
17441753
impl fmt::Display for YieldSource {
17451754
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17461755
f.write_str(match self {
1747-
YieldSource::Await => "`await`",
1756+
YieldSource::Await { .. } => "`await`",
17481757
YieldSource::Yield => "`yield`",
17491758
})
17501759
}
@@ -1755,7 +1764,7 @@ impl From<GeneratorKind> for YieldSource {
17551764
match kind {
17561765
// Guess based on the kind of the current generator.
17571766
GeneratorKind::Gen => Self::Yield,
1758-
GeneratorKind::Async(_) => Self::Await,
1767+
GeneratorKind::Async(_) => Self::Await { expr: None },
17591768
}
17601769
}
17611770
}

src/librustc_trait_selection/traits/error_reporting/suggestions.rs

Lines changed: 162 additions & 82 deletions
Large diffs are not rendered by default.

src/librustc_typeck/check/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1797,7 +1797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17971797
// we know that the yield type must be `()`; however, the context won't contain this
17981798
// information. Hence, we check the source of the yield expression here and check its
17991799
// value's type against `()` (this check should always hold).
1800-
None if src == &hir::YieldSource::Await => {
1800+
None if src.is_await() => {
18011801
self.check_expr_coercable_to_type(&value, self.tcx.mk_unit());
18021802
self.tcx.mk_unit()
18031803
}

src/test/ui/async-await/async-fn-nonsend.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await
1212
--> $DIR/async-fn-nonsend.rs:24:5
1313
|
1414
LL | let x = non_send();
15-
| - has type `impl std::fmt::Debug`
15+
| - has type `impl std::fmt::Debug` which is not `Send`
1616
LL | drop(x);
1717
LL | fut().await;
1818
| ^^^^^^^^^^^ await occurs here, with `x` maybe used later
@@ -33,7 +33,7 @@ note: future is not `Send` as this value is used across an await
3333
--> $DIR/async-fn-nonsend.rs:33:20
3434
|
3535
LL | match Some(non_send()) {
36-
| ---------- has type `impl std::fmt::Debug`
36+
| ---------- has type `impl std::fmt::Debug` which is not `Send`
3737
LL | Some(_) => fut().await,
3838
| ^^^^^^^^^^^ await occurs here, with `non_send()` maybe used later
3939
...
@@ -54,7 +54,7 @@ note: future is not `Send` as this value is used across an await
5454
--> $DIR/async-fn-nonsend.rs:42:9
5555
|
5656
LL | let f: &mut std::fmt::Formatter = panic!();
57-
| - has type `&mut std::fmt::Formatter<'_>`
57+
| - has type `&mut std::fmt::Formatter<'_>` which is not `Send`
5858
LL | if non_sync().fmt(f).unwrap() == () {
5959
LL | fut().await;
6060
| ^^^^^^^^^^^ await occurs here, with `f` maybe used later

src/test/ui/async-await/issue-64130-1-sync.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ note: future is not `Sync` as this value is used across an await
1212
--> $DIR/issue-64130-1-sync.rs:15:5
1313
|
1414
LL | let x = Foo;
15-
| - has type `Foo`
15+
| - has type `Foo` which is not `Sync`
1616
LL | baz().await;
1717
| ^^^^^^^^^^^ await occurs here, with `x` maybe used later
1818
LL | }

src/test/ui/async-await/issue-64130-2-send.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await
1212
--> $DIR/issue-64130-2-send.rs:15:5
1313
|
1414
LL | let x = Foo;
15-
| - has type `Foo`
15+
| - has type `Foo` which is not `Send`
1616
LL | baz().await;
1717
| ^^^^^^^^^^^ await occurs here, with `x` maybe used later
1818
LL | }

src/test/ui/async-await/issue-64130-3-other.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ note: future does not implement `Qux` as this value is used across an await
1616
--> $DIR/issue-64130-3-other.rs:18:5
1717
|
1818
LL | let x = Foo;
19-
| - has type `Foo`
19+
| - has type `Foo` which does not implement `Qux`
2020
LL | baz().await;
2121
| ^^^^^^^^^^^ await occurs here, with `x` maybe used later
2222
LL | }

src/test/ui/async-await/issue-64130-4-async-move.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: future cannot be sent between threads safely
22
--> $DIR/issue-64130-4-async-move.rs:15:17
33
|
44
LL | pub fn foo() -> impl Future + Send {
5-
| ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
5+
| ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
66
...
77
LL | / async move {
88
LL | | match client.status() {
@@ -18,7 +18,7 @@ note: future is not `Send` as this value is used across an await
1818
--> $DIR/issue-64130-4-async-move.rs:21:26
1919
|
2020
LL | match client.status() {
21-
| ------ has type `&Client`
21+
| ------ has type `&Client` which is not `Send`
2222
LL | 200 => {
2323
LL | let _x = get().await;
2424
| ^^^^^^^^^^^ await occurs here, with `client` maybe used later

src/test/ui/async-await/issue-64130-non-send-future-diags.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await
1212
--> $DIR/issue-64130-non-send-future-diags.rs:15:5
1313
|
1414
LL | let g = x.lock().unwrap();
15-
| - has type `std::sync::MutexGuard<'_, u32>`
15+
| - has type `std::sync::MutexGuard<'_, u32>` which is not `Send`
1616
LL | baz().await;
1717
| ^^^^^^^^^^^ await occurs here, with `g` maybe used later
1818
LL | }

0 commit comments

Comments
 (0)