Skip to content

Commit 5374688

Browse files
add tests for async await
1 parent 8e4a971 commit 5374688

File tree

8 files changed

+162
-15
lines changed

8 files changed

+162
-15
lines changed

compiler/rustc_hir/src/hir.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1296,7 +1296,6 @@ pub struct Stmt<'hir> {
12961296
#[derive(Debug, HashStable_Generic)]
12971297
pub enum StmtKind<'hir> {
12981298
/// A local (`let`) binding.
1299-
/// FIXME: bundle the last two components into another `struct`
13001299
Local(&'hir Local<'hir>),
13011300

13021301
/// An item binding.

compiler/rustc_hir/src/intravisit.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1058,9 +1058,9 @@ pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) {
10581058

10591059
pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) {
10601060
visitor.visit_id(statement.hir_id);
1061-
match &statement.kind {
1061+
match statement.kind {
10621062
StmtKind::Local(ref local) => visitor.visit_local(local),
1063-
StmtKind::Item(item) => visitor.visit_nested_item(*item),
1063+
StmtKind::Item(item) => visitor.visit_nested_item(item),
10641064
StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => {
10651065
visitor.visit_expr(expression)
10661066
}

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
use crate::infer::type_variable::TypeVariableOriginKind;
22
use crate::infer::InferCtxt;
3-
use hir::LocalSource;
43
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
54
use rustc_hir as hir;
65
use rustc_hir::def::Res;
76
use rustc_hir::def::{CtorOf, DefKind, Namespace};
87
use rustc_hir::def_id::DefId;
98
use rustc_hir::intravisit::{self, Visitor};
10-
use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local};
9+
use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, LocalSource};
1110
use rustc_middle::hir::nested_filter;
1211
use rustc_middle::infer::unify_key::ConstVariableOriginKind;
1312
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};

compiler/rustc_mir_build/src/thir/cx/block.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl<'tcx> Cx<'tcx> {
4848
.filter_map(|(index, stmt)| {
4949
let hir_id = stmt.hir_id;
5050
let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id);
51-
match &stmt.kind {
51+
match stmt.kind {
5252
hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => {
5353
let stmt = Stmt {
5454
kind: StmtKind::Expr {
@@ -66,7 +66,7 @@ impl<'tcx> Cx<'tcx> {
6666
// ignore for purposes of the MIR
6767
None
6868
}
69-
hir::StmtKind::Local(local) => {
69+
hir::StmtKind::Local(ref local) => {
7070
let remainder_scope = region::Scope {
7171
id: block_id,
7272
data: region::ScopeData::Remainder(region::FirstStatementIndex::new(

compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -1215,12 +1215,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12151215
self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr);
12161216
let pat_ty = self.node_ty(decl.pat.hir_id);
12171217
self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, pat_ty);
1218-
}
12191218

1220-
/// Type check a `let` statement.
1221-
pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
1222-
self.check_decl(local.into());
1223-
if let Some(blk) = local.els {
1219+
if let Some(blk) = decl.els {
12241220
let previous_diverges = self.diverges.get();
12251221
let else_ty = self.check_block_with_expected(blk, NoExpectation);
12261222
let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
@@ -1233,6 +1229,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12331229
}
12341230
}
12351231

1232+
/// Type check a `let` statement.
1233+
pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
1234+
self.check_decl(local.into());
1235+
}
1236+
12361237
pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) {
12371238
// Don't do all the complex logic below for `DeclItem`.
12381239
match stmt.kind {

compiler/rustc_typeck/src/check/gather_locals.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,20 @@ pub(super) struct Declaration<'a> {
1616
pub ty: Option<&'a hir::Ty<'a>>,
1717
pub span: Span,
1818
pub init: Option<&'a hir::Expr<'a>>,
19+
pub els: Option<&'a hir::Block<'a>>,
1920
}
2021

2122
impl<'a> From<&'a hir::Local<'a>> for Declaration<'a> {
2223
fn from(local: &'a hir::Local<'a>) -> Self {
23-
let hir::Local { hir_id, pat, ty, span, init, .. } = *local;
24-
Declaration { hir_id, pat, ty, span, init }
24+
let hir::Local { hir_id, pat, ty, span, init, els, source: _ } = *local;
25+
Declaration { hir_id, pat, ty, span, init, els }
2526
}
2627
}
2728

2829
impl<'a> From<&'a hir::Let<'a>> for Declaration<'a> {
2930
fn from(let_expr: &'a hir::Let<'a>) -> Self {
3031
let hir::Let { hir_id, pat, ty, span, init } = *let_expr;
31-
Declaration { hir_id, pat, ty, span, init: Some(init) }
32+
Declaration { hir_id, pat, ty, span, init: Some(init), els: None }
3233
}
3334
}
3435

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// edition:2021
2+
#![feature(let_else)]
3+
use std::rc::Rc;
4+
5+
async fn foo(x: Option<bool>) {
6+
let Some(_) = x else {
7+
let r = Rc::new(());
8+
bar().await
9+
};
10+
}
11+
12+
async fn bar() -> ! {
13+
panic!()
14+
}
15+
16+
fn is_send<T: Send>(_: T) {}
17+
18+
async fn foo2(x: Option<bool>) {
19+
let Some(_) = x else {
20+
bar2(Rc::new(())).await
21+
};
22+
}
23+
24+
async fn bar2<T>(_: T) -> ! {
25+
panic!()
26+
}
27+
28+
async fn foo3(x: Option<bool>) {
29+
let Some(_) = x else {
30+
(Rc::new(()), bar().await);
31+
return;
32+
};
33+
}
34+
35+
async fn foo4(x: Option<bool>) {
36+
let Some(_) = x else {
37+
let r = Rc::new(());
38+
bar().await;
39+
println!("{:?}", r);
40+
return;
41+
};
42+
}
43+
44+
fn main() {
45+
is_send(foo(Some(true)));
46+
//~^ ERROR future cannot be sent between threads safely
47+
is_send(foo2(Some(true)));
48+
//~^ ERROR future cannot be sent between threads safely
49+
is_send(foo3(Some(true)));
50+
//~^ ERROR future cannot be sent between threads safely
51+
is_send(foo4(Some(true)));
52+
//~^ ERROR future cannot be sent between threads safely
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
error: future cannot be sent between threads safely
2+
--> $DIR/async-await-let-else.rs:45:13
3+
|
4+
LL | is_send(foo(Some(true)));
5+
| ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
6+
|
7+
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
8+
note: future is not `Send` as this value is used across an await
9+
--> $DIR/async-await-let-else.rs:8:14
10+
|
11+
LL | let r = Rc::new(());
12+
| - has type `Rc<()>` which is not `Send`
13+
LL | bar().await
14+
| ^^^^^^ await occurs here, with `r` maybe used later
15+
LL | };
16+
| - `r` is later dropped here
17+
note: required by a bound in `is_send`
18+
--> $DIR/async-await-let-else.rs:16:15
19+
|
20+
LL | fn is_send<T: Send>(_: T) {}
21+
| ^^^^ required by this bound in `is_send`
22+
23+
error: future cannot be sent between threads safely
24+
--> $DIR/async-await-let-else.rs:47:13
25+
|
26+
LL | is_send(foo2(Some(true)));
27+
| ^^^^^^^^^^^^^^^^ future returned by `foo2` is not `Send`
28+
|
29+
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
30+
note: future is not `Send` as this value is used across an await
31+
--> $DIR/async-await-let-else.rs:20:26
32+
|
33+
LL | bar2(Rc::new(())).await
34+
| ----------- ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
35+
| |
36+
| has type `Rc<()>` which is not `Send`
37+
LL | };
38+
| - `Rc::new(())` is later dropped here
39+
note: required by a bound in `is_send`
40+
--> $DIR/async-await-let-else.rs:16:15
41+
|
42+
LL | fn is_send<T: Send>(_: T) {}
43+
| ^^^^ required by this bound in `is_send`
44+
45+
error: future cannot be sent between threads safely
46+
--> $DIR/async-await-let-else.rs:49:13
47+
|
48+
LL | is_send(foo3(Some(true)));
49+
| ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send`
50+
|
51+
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
52+
note: future is not `Send` as this value is used across an await
53+
--> $DIR/async-await-let-else.rs:30:28
54+
|
55+
LL | (Rc::new(()), bar().await);
56+
| ----------- ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
57+
| |
58+
| has type `Rc<()>` which is not `Send`
59+
note: `Rc::new(())` is later dropped here
60+
--> $DIR/async-await-let-else.rs:30:35
61+
|
62+
LL | (Rc::new(()), bar().await);
63+
| ^
64+
note: required by a bound in `is_send`
65+
--> $DIR/async-await-let-else.rs:16:15
66+
|
67+
LL | fn is_send<T: Send>(_: T) {}
68+
| ^^^^ required by this bound in `is_send`
69+
70+
error: future cannot be sent between threads safely
71+
--> $DIR/async-await-let-else.rs:51:13
72+
|
73+
LL | is_send(foo4(Some(true)));
74+
| ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send`
75+
|
76+
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
77+
note: future is not `Send` as this value is used across an await
78+
--> $DIR/async-await-let-else.rs:38:14
79+
|
80+
LL | let r = Rc::new(());
81+
| - has type `Rc<()>` which is not `Send`
82+
LL | bar().await;
83+
| ^^^^^^ await occurs here, with `r` maybe used later
84+
...
85+
LL | };
86+
| - `r` is later dropped here
87+
note: required by a bound in `is_send`
88+
--> $DIR/async-await-let-else.rs:16:15
89+
|
90+
LL | fn is_send<T: Send>(_: T) {}
91+
| ^^^^ required by this bound in `is_send`
92+
93+
error: aborting due to 4 previous errors
94+

0 commit comments

Comments
 (0)