diff options
| author | bors <bors@rust-lang.org> | 2019-10-03 12:19:21 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-10-03 12:19:21 +0000 |
| commit | cfb6d84720019236e33872e145d187dfd6e81090 (patch) | |
| tree | 0832dd156d9ad55c93bee020fee1ea14c737a55e /src/librustc | |
| parent | 0221e265621a5fcc68ca62bdcdeabad1882a0e9a (diff) | |
| parent | a807032f9e4e4b43db17a1f17be766bb02d23a57 (diff) | |
| download | rust-cfb6d84720019236e33872e145d187dfd6e81090.tar.gz rust-cfb6d84720019236e33872e145d187dfd6e81090.zip | |
Auto merge of #64999 - nikomatsakis:issue-60424-async-return-inference, r=cramertj
extract expected return type for async fn generators Fixes #60424 cc @Centril, I know you've been eager to see this fixed. r? @cramertj
Diffstat (limited to 'src/librustc')
| -rw-r--r-- | src/librustc/hir/lowering/expr.rs | 30 | ||||
| -rw-r--r-- | src/librustc/hir/lowering/item.rs | 6 | ||||
| -rw-r--r-- | src/librustc/hir/mod.rs | 39 | ||||
| -rw-r--r-- | src/librustc/infer/mod.rs | 11 |
4 files changed, 69 insertions, 17 deletions
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index db5b197c5d6..d5fcc0ef6ed 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -89,9 +89,14 @@ impl LoweringContext<'_> { hir::MatchSource::Normal, ), ExprKind::Async(capture_clause, closure_node_id, ref block) => { - self.make_async_expr(capture_clause, closure_node_id, None, block.span, |this| { - this.with_new_scopes(|this| this.lower_block_expr(block)) - }) + self.make_async_expr( + capture_clause, + closure_node_id, + None, + block.span, + hir::AsyncGeneratorKind::Block, + |this| this.with_new_scopes(|this| this.lower_block_expr(block)), + ) } ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr), ExprKind::Closure( @@ -457,6 +462,7 @@ impl LoweringContext<'_> { closure_node_id: NodeId, ret_ty: Option<AstP<Ty>>, span: Span, + async_gen_kind: hir::AsyncGeneratorKind, body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr, ) -> hir::ExprKind { let capture_clause = self.lower_capture_clause(capture_clause); @@ -470,7 +476,7 @@ impl LoweringContext<'_> { }; let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None); let body_id = self.lower_fn_body(&ast_decl, |this| { - this.generator_kind = Some(hir::GeneratorKind::Async); + this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind)); body(this) }); @@ -522,7 +528,7 @@ impl LoweringContext<'_> { /// ``` fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind { match self.generator_kind { - Some(hir::GeneratorKind::Async) => {}, + Some(hir::GeneratorKind::Async(_)) => {}, Some(hir::GeneratorKind::Gen) | None => { let mut err = struct_span_err!( @@ -727,7 +733,7 @@ impl LoweringContext<'_> { Movability::Static => hir::GeneratorMovability::Static, }) }, - Some(hir::GeneratorKind::Async) => { + Some(hir::GeneratorKind::Async(_)) => { bug!("non-`async` closure body turned `async` during lowering"); }, None => { @@ -786,10 +792,12 @@ impl LoweringContext<'_> { None }; let async_body = this.make_async_expr( - capture_clause, closure_id, async_ret_ty, body.span, - |this| { - this.with_new_scopes(|this| this.lower_expr(body)) - } + capture_clause, + closure_id, + async_ret_ty, + body.span, + hir::AsyncGeneratorKind::Closure, + |this| this.with_new_scopes(|this| this.lower_expr(body)), ); this.expr(fn_decl_span, async_body, ThinVec::new()) }); @@ -1005,7 +1013,7 @@ impl LoweringContext<'_> { fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind { match self.generator_kind { Some(hir::GeneratorKind::Gen) => {}, - Some(hir::GeneratorKind::Async) => { + Some(hir::GeneratorKind::Async(_)) => { span_err!( self.sess, span, diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 7159db736a7..548a2fedfff 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -1222,7 +1222,11 @@ impl LoweringContext<'_> { } let async_expr = this.make_async_expr( - CaptureBy::Value, closure_id, None, body.span, + CaptureBy::Value, + closure_id, + None, + body.span, + hir::AsyncGeneratorKind::Fn, |this| { // Create a block from the user's function body: let user_body = this.lower_block_expr(body); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 9b4d88a5a09..d5892794d64 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1362,21 +1362,49 @@ impl Body { } /// The type of source expression that caused this generator to be created. -// Not `IsAsync` because we want to eventually add support for `AsyncGen` #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum GeneratorKind { - /// An `async` block or function. - Async, + /// An explicit `async` block or the body of an async function. + Async(AsyncGeneratorKind), + /// A generator literal created via a `yield` inside a closure. Gen, } impl fmt::Display for GeneratorKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + GeneratorKind::Async(k) => fmt::Display::fmt(k, f), + GeneratorKind::Gen => f.write_str("generator"), + } + } +} + +/// In the case of a generator created as part of an async construct, +/// which kind of async construct caused it to be created? +/// +/// This helps error messages but is also used to drive coercions in +/// type-checking (see #60424). +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, + RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +pub enum AsyncGeneratorKind { + /// An explicit `async` block written by the user. + Block, + + /// An explicit `async` block written by the user. + Closure, + + /// The `async` block generated as the body of an async function. + Fn, +} + +impl fmt::Display for AsyncGeneratorKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match self { - GeneratorKind::Async => "`async` object", - GeneratorKind::Gen => "generator", + AsyncGeneratorKind::Block => "`async` block", + AsyncGeneratorKind::Closure => "`async` closure body", + AsyncGeneratorKind::Fn => "`async fn` body", }) } } @@ -1758,6 +1786,7 @@ pub struct Destination { pub enum GeneratorMovability { /// May contain self-references, `!Unpin`. Static, + /// Must not contain self-references, `Unpin`. Movable, } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 35db82406ab..1f75ebbd348 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1319,6 +1319,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + /// Resolve any type variables found in `value` -- but only one + /// level. So, if the variable `?X` is bound to some type + /// `Foo<?Y>`, then this would return `Foo<?Y>` (but `?Y` may + /// itself be bound to a type). + /// + /// Useful when you only need to inspect the outermost level of + /// the type and don't care about nested types (or perhaps you + /// will be resolving them as well, e.g. in a loop). pub fn shallow_resolve<T>(&self, value: T) -> T where T: TypeFoldable<'tcx>, @@ -1579,6 +1587,9 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> { ShallowResolver { infcx } } + /// If `typ` is a type variable of some kind, resolve it one level + /// (but do not resolve types found in the result). If `typ` is + /// not a type variable, just return it unmodified. pub fn shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> { match typ.kind { ty::Infer(ty::TyVar(v)) => { |
