From 50e0c0d97bba3a0c954f29ebc6ed2d7a7f9b55b5 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 1 Oct 2020 09:28:25 -0700 Subject: [PATCH] Give better const-checking error for `async` blocks --- compiler/rustc_mir/src/transform/check_consts/ops.rs | 5 +++-- .../rustc_mir/src/transform/check_consts/validation.rs | 10 +++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index 25ed7859d21..32e233e337d 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -151,14 +151,15 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder< } #[derive(Debug)] -pub struct Generator; +pub struct Generator(pub hir::GeneratorKind); impl NonConstOp for Generator { fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status { Status::Forbidden } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { - ccx.tcx.sess.struct_span_err(span, "Generators and `async` functions cannot be `const`") + let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind()); + ccx.tcx.sess.struct_span_err(span, &msg) } } diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index ab63fd03a33..4e714bfeed3 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -770,6 +770,14 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location return; } + // `async` blocks get lowered to `std::future::from_generator(/* a closure */)`. + let is_async_block = Some(callee) == tcx.lang_items().from_generator_fn(); + if is_async_block { + let kind = hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block); + self.check_op(ops::Generator(kind)); + return; + } + // HACK: This is to "unstabilize" the `transmute` intrinsic // within const fns. `transmute` is allowed in all other const contexts. // This won't really scale to more intrinsics or functions. Let's allow const @@ -869,7 +877,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location TerminatorKind::Abort => self.check_op(ops::Abort), TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => { - self.check_op(ops::Generator) + self.check_op(ops::Generator(hir::GeneratorKind::Gen)) } TerminatorKind::Assert { .. } -- 2.44.0