Detect allocator for box in must_not_suspend lint

This commit is contained in:
Michael Goulet 2024-03-18 13:41:08 -04:00
parent 3cdcdaf31b
commit 0db06bf004
3 changed files with 62 additions and 4 deletions

View File

@ -1964,15 +1964,21 @@ fn check_must_not_suspend_ty<'tcx>(
debug!("Checking must_not_suspend for {}", ty); debug!("Checking must_not_suspend for {}", ty);
match *ty.kind() { match *ty.kind() {
ty::Adt(..) if ty.is_box() => { ty::Adt(_, args) if ty.is_box() => {
let boxed_ty = ty.boxed_ty(); let boxed_ty = args.type_at(0);
let descr_pre = &format!("{}boxed ", data.descr_pre); let allocator_ty = args.type_at(1);
check_must_not_suspend_ty( check_must_not_suspend_ty(
tcx, tcx,
boxed_ty, boxed_ty,
hir_id, hir_id,
param_env, param_env,
SuspendCheckData { descr_pre, ..data }, SuspendCheckData { descr_pre: &format!("{}boxed ", data.descr_pre), ..data },
) || check_must_not_suspend_ty(
tcx,
allocator_ty,
hir_id,
param_env,
SuspendCheckData { descr_pre: &format!("{}allocator ", data.descr_pre), ..data },
) )
} }
ty::Adt(def, _) => check_must_not_suspend_def(tcx, def.did(), hir_id, data), ty::Adt(def, _) => check_must_not_suspend_def(tcx, def.did(), hir_id, data),

View File

@ -0,0 +1,30 @@
//@ edition: 2021
#![feature(must_not_suspend, allocator_api)]
#![deny(must_not_suspend)]
use std::alloc::*;
use std::ptr::NonNull;
#[must_not_suspend]
struct MyAllocatorWhichMustNotSuspend;
unsafe impl Allocator for MyAllocatorWhichMustNotSuspend {
fn allocate(&self, l: Layout) -> Result<NonNull<[u8]>, AllocError> {
Global.allocate(l)
}
unsafe fn deallocate(&self, p: NonNull<u8>, l: Layout) {
Global.deallocate(p, l)
}
}
async fn suspend() {}
async fn foo() {
let x = Box::new_in(1i32, MyAllocatorWhichMustNotSuspend);
//~^ ERROR allocator `MyAllocatorWhichMustNotSuspend` held across a suspend point, but should not be
suspend().await;
drop(x);
}
fn main() {}

View File

@ -0,0 +1,22 @@
error: allocator `MyAllocatorWhichMustNotSuspend` held across a suspend point, but should not be
--> $DIR/allocator.rs:24:9
|
LL | let x = Box::new_in(1i32, MyAllocatorWhichMustNotSuspend);
| ^
LL |
LL | suspend().await;
| ----- the value is held across this suspend point
|
help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
--> $DIR/allocator.rs:24:9
|
LL | let x = Box::new_in(1i32, MyAllocatorWhichMustNotSuspend);
| ^
note: the lint level is defined here
--> $DIR/allocator.rs:4:9
|
LL | #![deny(must_not_suspend)]
| ^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error