1
Fork 0

Give better const-checking error for async blocks

This commit is contained in:
Dylan MacKenzie 2020-10-01 09:28:25 -07:00
parent 782013564e
commit 50e0c0d97b
2 changed files with 12 additions and 3 deletions

View file

@ -151,14 +151,15 @@ impl NonConstOp for FnPtrCast {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Generator; pub struct Generator(pub hir::GeneratorKind);
impl NonConstOp for Generator { impl NonConstOp for Generator {
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status { fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
Status::Forbidden Status::Forbidden
} }
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { 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)
} }
} }

View file

@ -770,6 +770,14 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
return; 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 // HACK: This is to "unstabilize" the `transmute` intrinsic
// within const fns. `transmute` is allowed in all other const contexts. // 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 // This won't really scale to more intrinsics or functions. Let's allow const
@ -869,7 +877,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
TerminatorKind::Abort => self.check_op(ops::Abort), TerminatorKind::Abort => self.check_op(ops::Abort),
TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => { TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
self.check_op(ops::Generator) self.check_op(ops::Generator(hir::GeneratorKind::Gen))
} }
TerminatorKind::Assert { .. } TerminatorKind::Assert { .. }