Skip to content

Commit 3c3b398

Browse files
authored
Rollup merge of #122701 - compiler-errors:allocator-suspend, r=oli-obk
Detect allocator for box in `must_not_suspend` lint I don't expect this to happen in practice, but better to check than not. Fixes #122643
2 parents af48242 + 0db06bf commit 3c3b398

File tree

3 files changed

+62
-4
lines changed

3 files changed

+62
-4
lines changed

Diff for: compiler/rustc_mir_transform/src/coroutine.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -1964,15 +1964,21 @@ fn check_must_not_suspend_ty<'tcx>(
19641964
debug!("Checking must_not_suspend for {}", ty);
19651965

19661966
match *ty.kind() {
1967-
ty::Adt(..) if ty.is_box() => {
1968-
let boxed_ty = ty.boxed_ty();
1969-
let descr_pre = &format!("{}boxed ", data.descr_pre);
1967+
ty::Adt(_, args) if ty.is_box() => {
1968+
let boxed_ty = args.type_at(0);
1969+
let allocator_ty = args.type_at(1);
19701970
check_must_not_suspend_ty(
19711971
tcx,
19721972
boxed_ty,
19731973
hir_id,
19741974
param_env,
1975-
SuspendCheckData { descr_pre, ..data },
1975+
SuspendCheckData { descr_pre: &format!("{}boxed ", data.descr_pre), ..data },
1976+
) || check_must_not_suspend_ty(
1977+
tcx,
1978+
allocator_ty,
1979+
hir_id,
1980+
param_env,
1981+
SuspendCheckData { descr_pre: &format!("{}allocator ", data.descr_pre), ..data },
19761982
)
19771983
}
19781984
ty::Adt(def, _) => check_must_not_suspend_def(tcx, def.did(), hir_id, data),

Diff for: tests/ui/lint/must_not_suspend/allocator.rs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//@ edition: 2021
2+
3+
#![feature(must_not_suspend, allocator_api)]
4+
#![deny(must_not_suspend)]
5+
6+
use std::alloc::*;
7+
use std::ptr::NonNull;
8+
9+
#[must_not_suspend]
10+
struct MyAllocatorWhichMustNotSuspend;
11+
12+
unsafe impl Allocator for MyAllocatorWhichMustNotSuspend {
13+
fn allocate(&self, l: Layout) -> Result<NonNull<[u8]>, AllocError> {
14+
Global.allocate(l)
15+
}
16+
unsafe fn deallocate(&self, p: NonNull<u8>, l: Layout) {
17+
Global.deallocate(p, l)
18+
}
19+
}
20+
21+
async fn suspend() {}
22+
23+
async fn foo() {
24+
let x = Box::new_in(1i32, MyAllocatorWhichMustNotSuspend);
25+
//~^ ERROR allocator `MyAllocatorWhichMustNotSuspend` held across a suspend point, but should not be
26+
suspend().await;
27+
drop(x);
28+
}
29+
30+
fn main() {}

Diff for: tests/ui/lint/must_not_suspend/allocator.stderr

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: allocator `MyAllocatorWhichMustNotSuspend` held across a suspend point, but should not be
2+
--> $DIR/allocator.rs:24:9
3+
|
4+
LL | let x = Box::new_in(1i32, MyAllocatorWhichMustNotSuspend);
5+
| ^
6+
LL |
7+
LL | suspend().await;
8+
| ----- the value is held across this suspend point
9+
|
10+
help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
11+
--> $DIR/allocator.rs:24:9
12+
|
13+
LL | let x = Box::new_in(1i32, MyAllocatorWhichMustNotSuspend);
14+
| ^
15+
note: the lint level is defined here
16+
--> $DIR/allocator.rs:4:9
17+
|
18+
LL | #![deny(must_not_suspend)]
19+
| ^^^^^^^^^^^^^^^^
20+
21+
error: aborting due to 1 previous error
22+

0 commit comments

Comments
 (0)