about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDing Xiang Fei <dingxiangfei2009@protonmail.ch>2022-07-11 23:20:27 +0200
committerDing Xiang Fei <dingxiangfei2009@protonmail.ch>2022-07-11 23:20:39 +0200
commit5374688e1d8cbcff7d1d14bb34e38fe6fe7c233e (patch)
tree54e9111663c75c022f10d63cc9b0f6603a15f90c
parent8e4a9710841a21f77856ae1d8207015c220a1873 (diff)
downloadrust-5374688e1d8cbcff7d1d14bb34e38fe6fe7c233e.tar.gz
rust-5374688e1d8cbcff7d1d14bb34e38fe6fe7c233e.zip
add tests for async await
-rw-r--r--compiler/rustc_hir/src/hir.rs1
-rw-r--r--compiler/rustc_hir/src/intravisit.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs3
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/block.rs4
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs11
-rw-r--r--compiler/rustc_typeck/src/check/gather_locals.rs7
-rw-r--r--src/test/ui/async-await/async-await-let-else.rs53
-rw-r--r--src/test/ui/async-await/async-await-let-else.stderr94
8 files changed, 162 insertions, 15 deletions
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index c8a0ed39511..ed874ae829b 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1296,7 +1296,6 @@ pub struct Stmt<'hir> {
 #[derive(Debug, HashStable_Generic)]
 pub enum StmtKind<'hir> {
     /// A local (`let`) binding.
-    /// FIXME: bundle the last two components into another `struct`
     Local(&'hir Local<'hir>),
 
     /// An item binding.
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index ef1a30e142c..b5d9769c578 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -1058,9 +1058,9 @@ pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) {
 
 pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) {
     visitor.visit_id(statement.hir_id);
-    match &statement.kind {
+    match statement.kind {
         StmtKind::Local(ref local) => visitor.visit_local(local),
-        StmtKind::Item(item) => visitor.visit_nested_item(*item),
+        StmtKind::Item(item) => visitor.visit_nested_item(item),
         StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => {
             visitor.visit_expr(expression)
         }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index a0ec7f4fc6f..4d29fc46946 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -1,13 +1,12 @@
 use crate::infer::type_variable::TypeVariableOriginKind;
 use crate::infer::InferCtxt;
-use hir::LocalSource;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def::{CtorOf, DefKind, Namespace};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local};
+use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, LocalSource};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::infer::unify_key::ConstVariableOriginKind;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs
index 4079470c255..dccaa61ed89 100644
--- a/compiler/rustc_mir_build/src/thir/cx/block.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/block.rs
@@ -48,7 +48,7 @@ impl<'tcx> Cx<'tcx> {
             .filter_map(|(index, stmt)| {
                 let hir_id = stmt.hir_id;
                 let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id);
-                match &stmt.kind {
+                match stmt.kind {
                     hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => {
                         let stmt = Stmt {
                             kind: StmtKind::Expr {
@@ -66,7 +66,7 @@ impl<'tcx> Cx<'tcx> {
                         // ignore for purposes of the MIR
                         None
                     }
-                    hir::StmtKind::Local(local) => {
+                    hir::StmtKind::Local(ref local) => {
                         let remainder_scope = region::Scope {
                             id: block_id,
                             data: region::ScopeData::Remainder(region::FirstStatementIndex::new(
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 097b9c3f0f7..60ee2233ed9 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -1215,12 +1215,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr);
         let pat_ty = self.node_ty(decl.pat.hir_id);
         self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, pat_ty);
-    }
 
-    /// Type check a `let` statement.
-    pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
-        self.check_decl(local.into());
-        if let Some(blk) = local.els {
+        if let Some(blk) = decl.els {
             let previous_diverges = self.diverges.get();
             let else_ty = self.check_block_with_expected(blk, NoExpectation);
             let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
@@ -1233,6 +1229,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    /// Type check a `let` statement.
+    pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
+        self.check_decl(local.into());
+    }
+
     pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) {
         // Don't do all the complex logic below for `DeclItem`.
         match stmt.kind {
diff --git a/compiler/rustc_typeck/src/check/gather_locals.rs b/compiler/rustc_typeck/src/check/gather_locals.rs
index 859fc91f517..8f34a970f6f 100644
--- a/compiler/rustc_typeck/src/check/gather_locals.rs
+++ b/compiler/rustc_typeck/src/check/gather_locals.rs
@@ -16,19 +16,20 @@ pub(super) struct Declaration<'a> {
     pub ty: Option<&'a hir::Ty<'a>>,
     pub span: Span,
     pub init: Option<&'a hir::Expr<'a>>,
+    pub els: Option<&'a hir::Block<'a>>,
 }
 
 impl<'a> From<&'a hir::Local<'a>> for Declaration<'a> {
     fn from(local: &'a hir::Local<'a>) -> Self {
-        let hir::Local { hir_id, pat, ty, span, init, .. } = *local;
-        Declaration { hir_id, pat, ty, span, init }
+        let hir::Local { hir_id, pat, ty, span, init, els, source: _ } = *local;
+        Declaration { hir_id, pat, ty, span, init, els }
     }
 }
 
 impl<'a> From<&'a hir::Let<'a>> for Declaration<'a> {
     fn from(let_expr: &'a hir::Let<'a>) -> Self {
         let hir::Let { hir_id, pat, ty, span, init } = *let_expr;
-        Declaration { hir_id, pat, ty, span, init: Some(init) }
+        Declaration { hir_id, pat, ty, span, init: Some(init), els: None }
     }
 }
 
diff --git a/src/test/ui/async-await/async-await-let-else.rs b/src/test/ui/async-await/async-await-let-else.rs
new file mode 100644
index 00000000000..7ea07ae9add
--- /dev/null
+++ b/src/test/ui/async-await/async-await-let-else.rs
@@ -0,0 +1,53 @@
+// edition:2021
+#![feature(let_else)]
+use std::rc::Rc;
+
+async fn foo(x: Option<bool>) {
+    let Some(_) = x else {
+        let r = Rc::new(());
+        bar().await
+    };
+}
+
+async fn bar() -> ! {
+    panic!()
+}
+
+fn is_send<T: Send>(_: T) {}
+
+async fn foo2(x: Option<bool>) {
+    let Some(_) = x else {
+        bar2(Rc::new(())).await
+    };
+}
+
+async fn bar2<T>(_: T) -> ! {
+    panic!()
+}
+
+async fn foo3(x: Option<bool>) {
+    let Some(_) = x else {
+        (Rc::new(()), bar().await);
+        return;
+    };
+}
+
+async fn foo4(x: Option<bool>) {
+    let Some(_) = x else {
+        let r = Rc::new(());
+        bar().await;
+        println!("{:?}", r);
+        return;
+    };
+}
+
+fn main() {
+    is_send(foo(Some(true)));
+    //~^ ERROR future cannot be sent between threads safely
+    is_send(foo2(Some(true)));
+    //~^ ERROR future cannot be sent between threads safely
+    is_send(foo3(Some(true)));
+    //~^ ERROR future cannot be sent between threads safely
+    is_send(foo4(Some(true)));
+    //~^ ERROR future cannot be sent between threads safely
+}
diff --git a/src/test/ui/async-await/async-await-let-else.stderr b/src/test/ui/async-await/async-await-let-else.stderr
new file mode 100644
index 00000000000..4d23e27c426
--- /dev/null
+++ b/src/test/ui/async-await/async-await-let-else.stderr
@@ -0,0 +1,94 @@
+error: future cannot be sent between threads safely
+  --> $DIR/async-await-let-else.rs:45:13
+   |
+LL |     is_send(foo(Some(true)));
+   |             ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
+   |
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/async-await-let-else.rs:8:14
+   |
+LL |         let r = Rc::new(());
+   |             - has type `Rc<()>` which is not `Send`
+LL |         bar().await
+   |              ^^^^^^ await occurs here, with `r` maybe used later
+LL |     };
+   |     - `r` is later dropped here
+note: required by a bound in `is_send`
+  --> $DIR/async-await-let-else.rs:16:15
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   |               ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+  --> $DIR/async-await-let-else.rs:47:13
+   |
+LL |     is_send(foo2(Some(true)));
+   |             ^^^^^^^^^^^^^^^^ future returned by `foo2` is not `Send`
+   |
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/async-await-let-else.rs:20:26
+   |
+LL |         bar2(Rc::new(())).await
+   |              ----------- ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
+   |              |
+   |              has type `Rc<()>` which is not `Send`
+LL |     };
+   |      - `Rc::new(())` is later dropped here
+note: required by a bound in `is_send`
+  --> $DIR/async-await-let-else.rs:16:15
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   |               ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+  --> $DIR/async-await-let-else.rs:49:13
+   |
+LL |     is_send(foo3(Some(true)));
+   |             ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send`
+   |
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/async-await-let-else.rs:30:28
+   |
+LL |         (Rc::new(()), bar().await);
+   |          -----------       ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
+   |          |
+   |          has type `Rc<()>` which is not `Send`
+note: `Rc::new(())` is later dropped here
+  --> $DIR/async-await-let-else.rs:30:35
+   |
+LL |         (Rc::new(()), bar().await);
+   |                                   ^
+note: required by a bound in `is_send`
+  --> $DIR/async-await-let-else.rs:16:15
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   |               ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+  --> $DIR/async-await-let-else.rs:51:13
+   |
+LL |     is_send(foo4(Some(true)));
+   |             ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send`
+   |
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/async-await-let-else.rs:38:14
+   |
+LL |         let r = Rc::new(());
+   |             - has type `Rc<()>` which is not `Send`
+LL |         bar().await;
+   |              ^^^^^^ await occurs here, with `r` maybe used later
+...
+LL |     };
+   |     - `r` is later dropped here
+note: required by a bound in `is_send`
+  --> $DIR/async-await-let-else.rs:16:15
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   |               ^^^^ required by this bound in `is_send`
+
+error: aborting due to 4 previous errors
+