Skip to content

Commit cac5352

Browse files
Rollup merge of #77415 - ecstatic-morse:const-checking-async-block, r=oli-obk
Better error message for `async` blocks in a const-context Improves the error message for the case in #77361. r? @oli-obk
2 parents 18ac26d + b48def8 commit cac5352

File tree

4 files changed

+28
-3
lines changed

4 files changed

+28
-3
lines changed

compiler/rustc_mir/src/transform/check_consts/ops.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,15 @@ impl NonConstOp for FnPtrCast {
151151
}
152152

153153
#[derive(Debug)]
154-
pub struct Generator;
154+
pub struct Generator(pub hir::GeneratorKind);
155155
impl NonConstOp for Generator {
156156
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
157157
Status::Forbidden
158158
}
159159

160160
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
161-
ccx.tcx.sess.struct_span_err(span, "Generators and `async` functions cannot be `const`")
161+
let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind());
162+
ccx.tcx.sess.struct_span_err(span, &msg)
162163
}
163164
}
164165

compiler/rustc_mir/src/transform/check_consts/validation.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,14 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
770770
return;
771771
}
772772

773+
// `async` blocks get lowered to `std::future::from_generator(/* a closure */)`.
774+
let is_async_block = Some(callee) == tcx.lang_items().from_generator_fn();
775+
if is_async_block {
776+
let kind = hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block);
777+
self.check_op(ops::Generator(kind));
778+
return;
779+
}
780+
773781
// HACK: This is to "unstabilize" the `transmute` intrinsic
774782
// within const fns. `transmute` is allowed in all other const contexts.
775783
// 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> {
869877
TerminatorKind::Abort => self.check_op(ops::Abort),
870878

871879
TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
872-
self.check_op(ops::Generator)
880+
self.check_op(ops::Generator(hir::GeneratorKind::Gen))
873881
}
874882

875883
TerminatorKind::Assert { .. }

src/test/ui/consts/async-block.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// From <https://github.com/rust-lang/rust/issues/77361>
2+
3+
// edition:2018
4+
5+
const _: i32 = { core::mem::ManuallyDrop::new(async { 0 }); 4 };
6+
//~^ `async` block
7+
8+
fn main() {}

src/test/ui/consts/async-block.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: `async` blocks are not allowed in constants
2+
--> $DIR/async-block.rs:5:47
3+
|
4+
LL | const _: i32 = { core::mem::ManuallyDrop::new(async { 0 }); 4 };
5+
| ^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+

0 commit comments

Comments
 (0)