Skip to content

Commit

Permalink
Rollup merge of #77415 - ecstatic-morse:const-checking-async-block, r…
Browse files Browse the repository at this point in the history
…=oli-obk

Better error message for `async` blocks in a const-context

Improves the error message for the case in #77361.

r? @oli-obk
  • Loading branch information
jonas-schievink authored Oct 2, 2020
2 parents 18ac26d + b48def8 commit cac5352
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 3 deletions.
5 changes: 3 additions & 2 deletions compiler/rustc_mir/src/transform/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,15 @@ impl NonConstOp for FnPtrCast {
}

#[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)
}
}

Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_mir/src/transform/check_consts/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,14 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
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
Expand Down Expand Up @@ -869,7 +877,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
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 { .. }
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/consts/async-block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// From <https://github.com/rust-lang/rust/issues/77361>

// edition:2018

const _: i32 = { core::mem::ManuallyDrop::new(async { 0 }); 4 };
//~^ `async` block

fn main() {}
8 changes: 8 additions & 0 deletions src/test/ui/consts/async-block.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: `async` blocks are not allowed in constants
--> $DIR/async-block.rs:5:47
|
LL | const _: i32 = { core::mem::ManuallyDrop::new(async { 0 }); 4 };
| ^^^^^^^^^^^

error: aborting due to previous error

0 comments on commit cac5352

Please sign in to comment.