From 560e5dcbcf776e06302ecb2fa81f77313d514306 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 21 Jul 2025 18:35:34 +0000 Subject: [PATCH] Add test for upvar breakage --- .../drop-live-upvar-2.may_not_dangle.stderr | 18 +++++++++ tests/ui/async-await/drop-live-upvar-2.rs | 37 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 tests/ui/async-await/drop-live-upvar-2.may_not_dangle.stderr create mode 100644 tests/ui/async-await/drop-live-upvar-2.rs diff --git a/tests/ui/async-await/drop-live-upvar-2.may_not_dangle.stderr b/tests/ui/async-await/drop-live-upvar-2.may_not_dangle.stderr new file mode 100644 index 000000000000..34f6ba79246c --- /dev/null +++ b/tests/ui/async-await/drop-live-upvar-2.may_not_dangle.stderr @@ -0,0 +1,18 @@ +error[E0597]: `y` does not live long enough + --> $DIR/drop-live-upvar-2.rs:31:26 + | +LL | let y = (); + | - binding `y` declared here +LL | drop_me = Droppy(&y); + | ^^ borrowed value does not live long enough +... +LL | } + | - `y` dropped here while still borrowed +LL | } + | - borrow might be used here, when `fut` is dropped and runs the destructor for coroutine + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/async-await/drop-live-upvar-2.rs b/tests/ui/async-await/drop-live-upvar-2.rs new file mode 100644 index 000000000000..605db4c8f765 --- /dev/null +++ b/tests/ui/async-await/drop-live-upvar-2.rs @@ -0,0 +1,37 @@ +//@ revisions: may_dangle may_not_dangle +//@[may_dangle] check-pass +//@ edition: 2018 + +// Ensure that if a coroutine's interior has no drop types then we don't require the upvars to +// be *use-live*, but instead require them to be *drop-live*. In this case, `Droppy<&'?0 ()>` +// does not require that `'?0` is live for drops since the parameter is `#[may_dangle]` in +// the may_dangle revision, but not in the may_not_dangle revision. + +#![feature(dropck_eyepatch)] + +struct Droppy(T); + +#[cfg(may_dangle)] +unsafe impl<#[may_dangle] T> Drop for Droppy { + fn drop(&mut self) { + // This does not use `T` of course. + } +} + +#[cfg(may_not_dangle)] +impl Drop for Droppy { + fn drop(&mut self) {} +} + +fn main() { + let drop_me; + let fut; + { + let y = (); + drop_me = Droppy(&y); + //[may_not_dangle]~^ ERROR `y` does not live long enough + fut = async { + std::mem::drop(drop_me); + }; + } +}