Skip to content

Commit 6320b9e

Browse files
Check coroutine upvars and resume ty in dtorck constraint
1 parent 8f08b3a commit 6320b9e

File tree

3 files changed

+53
-3
lines changed

3 files changed

+53
-3
lines changed

compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -344,9 +344,14 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
344344
let args = args.as_coroutine();
345345

346346
// While we conservatively assume that all coroutines require drop
347-
// to avoid query cycles during MIR building, we can check the actual
348-
// witness during borrowck to avoid unnecessary liveness constraints.
349-
if args.witness().needs_drop(tcx, tcx.erase_regions(typing_env)) {
347+
// to avoid query cycles during MIR building, we can be more precise
348+
// here and check the specific components of the coroutines. This
349+
// includes the witness types, upvars, *and* the resume ty.
350+
let typing_env = tcx.erase_regions(typing_env);
351+
let needs_drop = args.witness().needs_drop(tcx, typing_env)
352+
|| args.upvar_tys().iter().any(|ty| ty.needs_drop(tcx, typing_env))
353+
|| args.resume_ty().needs_drop(tcx, typing_env);
354+
if needs_drop {
350355
constraints.outlives.extend(args.upvar_tys().iter().map(ty::GenericArg::from));
351356
constraints.outlives.push(args.resume_ty().into());
352357
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ edition: 2018
2+
// Regression test for <https://github.com/rust-lang/rust/issues/144155>.
3+
4+
struct NeedsDrop<'a>(&'a Vec<i32>);
5+
6+
async fn await_point() {}
7+
8+
impl Drop for NeedsDrop<'_> {
9+
fn drop(&mut self) {}
10+
}
11+
12+
fn foo() {
13+
let v = vec![1, 2, 3];
14+
let x = NeedsDrop(&v);
15+
let c = async {
16+
std::future::ready(()).await;
17+
drop(x);
18+
};
19+
drop(v);
20+
//~^ ERROR cannot move out of `v` because it is borrowed
21+
}
22+
23+
fn main() {}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0505]: cannot move out of `v` because it is borrowed
2+
--> $DIR/drop-live-upvar.rs:19:10
3+
|
4+
LL | let v = vec![1, 2, 3];
5+
| - binding `v` declared here
6+
LL | let x = NeedsDrop(&v);
7+
| -- borrow of `v` occurs here
8+
...
9+
LL | drop(v);
10+
| ^ move out of `v` occurs here
11+
LL |
12+
LL | }
13+
| - borrow might be used here, when `c` is dropped and runs the destructor for coroutine
14+
|
15+
help: consider cloning the value if the performance cost is acceptable
16+
|
17+
LL | let x = NeedsDrop(&v.clone());
18+
| ++++++++
19+
20+
error: aborting due to 1 previous error
21+
22+
For more information about this error, try `rustc --explain E0505`.

0 commit comments

Comments
 (0)