From 87816378ab4190583df1b74bcfeacb8bc5dd4d70 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 11 Feb 2024 22:09:28 +0000 Subject: [PATCH] Fix async closures in CTFE --- .../rustc_const_eval/src/interpret/util.rs | 1 + .../src/interpret/validity.rs | 4 +- src/tools/miri/tests/pass/async-closure.rs | 40 +++++++++++++++++++ .../miri/tests/pass/async-closure.stdout | 3 ++ 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/tools/miri/tests/pass/async-closure.rs create mode 100644 src/tools/miri/tests/pass/async-closure.stdout diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 416443f5f4d..52b79203d2b 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -34,6 +34,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { match *ty.kind() { ty::Param(_) => ControlFlow::Break(FoundParam), ty::Closure(def_id, args) + | ty::CoroutineClosure(def_id, args, ..) | ty::Coroutine(def_id, args, ..) | ty::FnDef(def_id, args) => { let instance = ty::InstanceDef::Item(def_id); diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 38aeace02ba..dd14542ad8f 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -236,8 +236,8 @@ fn aggregate_field_path_elem(&mut self, layout: TyAndLayout<'tcx>, field: usize) // Now we know we are projecting to a field, so figure out which one. match layout.ty.kind() { - // coroutines and closures. - ty::Closure(def_id, _) | ty::Coroutine(def_id, _) => { + // coroutines, closures, and coroutine-closures all have upvars that may be named. + ty::Closure(def_id, _) | ty::Coroutine(def_id, _) | ty::CoroutineClosure(def_id, _) => { let mut name = None; // FIXME this should be more descriptive i.e. CapturePlace instead of CapturedVar // https://github.com/rust-lang/project-rfc-2229/issues/46 diff --git a/src/tools/miri/tests/pass/async-closure.rs b/src/tools/miri/tests/pass/async-closure.rs new file mode 100644 index 00000000000..9b2fc2948bf --- /dev/null +++ b/src/tools/miri/tests/pass/async-closure.rs @@ -0,0 +1,40 @@ +#![feature(async_closure, noop_waker, async_fn_traits)] + +use std::future::Future; +use std::pin::pin; +use std::task::*; + +pub fn block_on(fut: impl Future) -> T { + let mut fut = pin!(fut); + let ctx = &mut Context::from_waker(Waker::noop()); + + loop { + match fut.as_mut().poll(ctx) { + Poll::Pending => {} + Poll::Ready(t) => break t, + } + } +} + +async fn call_once(f: impl async FnOnce(DropMe)) { + f(DropMe("world")).await; +} + +#[derive(Debug)] +struct DropMe(&'static str); + +impl Drop for DropMe { + fn drop(&mut self) { + println!("{}", self.0); + } +} + +pub fn main() { + block_on(async { + let b = DropMe("hello"); + let async_closure = async move |a: DropMe| { + println!("{a:?} {b:?}"); + }; + call_once(async_closure).await; + }); +} diff --git a/src/tools/miri/tests/pass/async-closure.stdout b/src/tools/miri/tests/pass/async-closure.stdout new file mode 100644 index 00000000000..34cfdedc44a --- /dev/null +++ b/src/tools/miri/tests/pass/async-closure.stdout @@ -0,0 +1,3 @@ +DropMe("world") DropMe("hello") +world +hello