diff options
| author | Brezak <[email protected]> | 2025-07-22 20:56:46 +0200 |
|---|---|---|
| committer | Brezak <[email protected]> | 2025-07-23 19:19:02 +0200 |
| commit | a52965dc5d3d0c706310998d3eda8bc15cd45b02 (patch) | |
| tree | 64087a9a6391c6ded8c7ddfb06652152b1b0759e | |
| parent | a5984a8298491ea748693783275d95286a481394 (diff) | |
embassy-executor: unsafe tasks as unsafe
| -rw-r--r-- | embassy-executor-macros/src/macros/task.rs | 15 | ||||
| -rw-r--r-- | embassy-executor/CHANGELOG.md | 1 | ||||
| -rw-r--r-- | embassy-executor/tests/ui.rs | 1 | ||||
| -rw-r--r-- | embassy-executor/tests/ui/task_safety_attribute.rs | 25 |
4 files changed, 41 insertions, 1 deletions
diff --git a/embassy-executor-macros/src/macros/task.rs b/embassy-executor-macros/src/macros/task.rs index 1c5e3571d..f01cc3b6c 100644 --- a/embassy-executor-macros/src/macros/task.rs +++ b/embassy-executor-macros/src/macros/task.rs | |||
| @@ -120,6 +120,18 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { | |||
| 120 | task_inner.vis = syn::Visibility::Inherited; | 120 | task_inner.vis = syn::Visibility::Inherited; |
| 121 | task_inner.sig.ident = task_inner_ident.clone(); | 121 | task_inner.sig.ident = task_inner_ident.clone(); |
| 122 | 122 | ||
| 123 | // Forcefully mark the inner task as safe. | ||
| 124 | // SAFETY: We only ever call task_inner in functions | ||
| 125 | // with the same safety preconditions as task_inner | ||
| 126 | task_inner.sig.unsafety = None; | ||
| 127 | let task_body = task_inner.body; | ||
| 128 | task_inner.body = quote! { | ||
| 129 | #[allow(unused_unsafe, reason = "Not all function bodies may require being in an unsafe block")] | ||
| 130 | unsafe { | ||
| 131 | #task_body | ||
| 132 | } | ||
| 133 | }; | ||
| 134 | |||
| 123 | // assemble the original input arguments, | 135 | // assemble the original input arguments, |
| 124 | // including any attributes that may have | 136 | // including any attributes that may have |
| 125 | // been applied previously | 137 | // been applied previously |
| @@ -186,6 +198,7 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { | |||
| 186 | // Copy the generics + where clause to avoid more spurious errors. | 198 | // Copy the generics + where clause to avoid more spurious errors. |
| 187 | let generics = &f.sig.generics; | 199 | let generics = &f.sig.generics; |
| 188 | let where_clause = &f.sig.generics.where_clause; | 200 | let where_clause = &f.sig.generics.where_clause; |
| 201 | let unsafety = &f.sig.unsafety; | ||
| 189 | 202 | ||
| 190 | let result = quote! { | 203 | let result = quote! { |
| 191 | // This is the user's task function, renamed. | 204 | // This is the user's task function, renamed. |
| @@ -196,7 +209,7 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { | |||
| 196 | #task_inner | 209 | #task_inner |
| 197 | 210 | ||
| 198 | #(#task_outer_attrs)* | 211 | #(#task_outer_attrs)* |
| 199 | #visibility fn #task_ident #generics (#fargs) -> #embassy_executor::SpawnToken<impl Sized> #where_clause{ | 212 | #visibility #unsafety fn #task_ident #generics (#fargs) -> #embassy_executor::SpawnToken<impl Sized> #where_clause{ |
| 200 | #task_outer_body | 213 | #task_outer_body |
| 201 | } | 214 | } |
| 202 | 215 | ||
diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 914863a83..7404961f3 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md | |||
| @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
| 21 | - Added support for `-> impl Future<Output = ()>` in `#[task]` | 21 | - Added support for `-> impl Future<Output = ()>` in `#[task]` |
| 22 | - Fixed `Send` unsoundness with `-> impl Future` tasks | 22 | - Fixed `Send` unsoundness with `-> impl Future` tasks |
| 23 | - Marked `Spawner::for_current_executor` as `unsafe` | 23 | - Marked `Spawner::for_current_executor` as `unsafe` |
| 24 | - `#[task]` now properly marks the generated function as unsafe if the task is marked unsafe | ||
| 24 | 25 | ||
| 25 | ## 0.7.0 - 2025-01-02 | 26 | ## 0.7.0 - 2025-01-02 |
| 26 | 27 | ||
diff --git a/embassy-executor/tests/ui.rs b/embassy-executor/tests/ui.rs index 7757775ee..8b83cd368 100644 --- a/embassy-executor/tests/ui.rs +++ b/embassy-executor/tests/ui.rs | |||
| @@ -32,4 +32,5 @@ fn ui() { | |||
| 32 | t.compile_fail("tests/ui/self.rs"); | 32 | t.compile_fail("tests/ui/self.rs"); |
| 33 | t.compile_fail("tests/ui/type_error.rs"); | 33 | t.compile_fail("tests/ui/type_error.rs"); |
| 34 | t.compile_fail("tests/ui/where_clause.rs"); | 34 | t.compile_fail("tests/ui/where_clause.rs"); |
| 35 | t.pass("tests/ui/task_safety_attribute.rs"); | ||
| 35 | } | 36 | } |
diff --git a/embassy-executor/tests/ui/task_safety_attribute.rs b/embassy-executor/tests/ui/task_safety_attribute.rs new file mode 100644 index 000000000..ab5a2f99f --- /dev/null +++ b/embassy-executor/tests/ui/task_safety_attribute.rs | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | #![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] | ||
| 2 | #![deny(unused_unsafe)] | ||
| 3 | |||
| 4 | use std::mem; | ||
| 5 | |||
| 6 | #[embassy_executor::task] | ||
| 7 | async fn safe() {} | ||
| 8 | |||
| 9 | #[embassy_executor::task] | ||
| 10 | async unsafe fn not_safe() {} | ||
| 11 | |||
| 12 | #[export_name = "__pender"] | ||
| 13 | fn pender(_: *mut ()) { | ||
| 14 | // The test doesn't link if we don't include this. | ||
| 15 | // We never call this anyway. | ||
| 16 | } | ||
| 17 | |||
| 18 | fn main() { | ||
| 19 | let _forget_me = safe(); | ||
| 20 | // SAFETY: not_safe has not safety preconditions | ||
| 21 | let _forget_me2 = unsafe { not_safe() }; | ||
| 22 | |||
| 23 | mem::forget(_forget_me); | ||
| 24 | mem::forget(_forget_me2); | ||
| 25 | } | ||
