diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-03-08 01:59:06 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-03-08 01:59:06 +0100 |
| commit | a614e697d0ab8f45c59e136ad5015cfdedac50c3 (patch) | |
| tree | 4b23008751c72cafe82e551ddd68a8d271878049 | |
| parent | bd4c4209af3738e3b2d6b059670f9ed76e2f32ff (diff) | |
macros: better validation of function signatures.
Fixes #1266
| -rw-r--r-- | embassy-macros/src/macros/main.rs | 21 | ||||
| -rw-r--r-- | embassy-macros/src/macros/task.rs | 23 |
2 files changed, 43 insertions, 1 deletions
diff --git a/embassy-macros/src/macros/main.rs b/embassy-macros/src/macros/main.rs index 18f7c36c4..7af4ef836 100644 --- a/embassy-macros/src/macros/main.rs +++ b/embassy-macros/src/macros/main.rs | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | use darling::FromMeta; | 1 | use darling::FromMeta; |
| 2 | use proc_macro2::TokenStream; | 2 | use proc_macro2::TokenStream; |
| 3 | use quote::quote; | 3 | use quote::quote; |
| 4 | use syn::{ReturnType, Type}; | ||
| 4 | 5 | ||
| 5 | use crate::util::ctxt::Ctxt; | 6 | use crate::util::ctxt::Ctxt; |
| 6 | 7 | ||
| @@ -76,6 +77,26 @@ pub fn run(args: syn::AttributeArgs, f: syn::ItemFn, main: TokenStream) -> Resul | |||
| 76 | if !f.sig.generics.params.is_empty() { | 77 | if !f.sig.generics.params.is_empty() { |
| 77 | ctxt.error_spanned_by(&f.sig, "main function must not be generic"); | 78 | ctxt.error_spanned_by(&f.sig, "main function must not be generic"); |
| 78 | } | 79 | } |
| 80 | if !f.sig.generics.where_clause.is_none() { | ||
| 81 | ctxt.error_spanned_by(&f.sig, "main function must not have `where` clauses"); | ||
| 82 | } | ||
| 83 | if !f.sig.abi.is_none() { | ||
| 84 | ctxt.error_spanned_by(&f.sig, "main function must not have an ABI qualifier"); | ||
| 85 | } | ||
| 86 | if !f.sig.variadic.is_none() { | ||
| 87 | ctxt.error_spanned_by(&f.sig, "main function must not be variadic"); | ||
| 88 | } | ||
| 89 | match &f.sig.output { | ||
| 90 | ReturnType::Default => {} | ||
| 91 | ReturnType::Type(_, ty) => match &**ty { | ||
| 92 | Type::Tuple(tuple) if tuple.elems.is_empty() => {} | ||
| 93 | Type::Never(_) => {} | ||
| 94 | _ => ctxt.error_spanned_by( | ||
| 95 | &f.sig, | ||
| 96 | "main function must either not return a value, return `()` or return `!`", | ||
| 97 | ), | ||
| 98 | }, | ||
| 99 | } | ||
| 79 | 100 | ||
| 80 | if fargs.len() != 1 { | 101 | if fargs.len() != 1 { |
| 81 | ctxt.error_spanned_by(&f.sig, "main function must have 1 argument: the spawner."); | 102 | ctxt.error_spanned_by(&f.sig, "main function must have 1 argument: the spawner."); |
diff --git a/embassy-macros/src/macros/task.rs b/embassy-macros/src/macros/task.rs index 90d2cd893..9f30cf43e 100644 --- a/embassy-macros/src/macros/task.rs +++ b/embassy-macros/src/macros/task.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | use darling::FromMeta; | 1 | use darling::FromMeta; |
| 2 | use proc_macro2::TokenStream; | 2 | use proc_macro2::TokenStream; |
| 3 | use quote::{format_ident, quote}; | 3 | use quote::{format_ident, quote}; |
| 4 | use syn::{parse_quote, ItemFn}; | 4 | use syn::{parse_quote, ItemFn, ReturnType, Type}; |
| 5 | 5 | ||
| 6 | use crate::util::ctxt::Ctxt; | 6 | use crate::util::ctxt::Ctxt; |
| 7 | 7 | ||
| @@ -24,6 +24,27 @@ pub fn run(args: syn::AttributeArgs, f: syn::ItemFn) -> Result<TokenStream, Toke | |||
| 24 | if !f.sig.generics.params.is_empty() { | 24 | if !f.sig.generics.params.is_empty() { |
| 25 | ctxt.error_spanned_by(&f.sig, "task functions must not be generic"); | 25 | ctxt.error_spanned_by(&f.sig, "task functions must not be generic"); |
| 26 | } | 26 | } |
| 27 | if !f.sig.generics.where_clause.is_none() { | ||
| 28 | ctxt.error_spanned_by(&f.sig, "task functions must not have `where` clauses"); | ||
| 29 | } | ||
| 30 | if !f.sig.abi.is_none() { | ||
| 31 | ctxt.error_spanned_by(&f.sig, "task functions must not have an ABI qualifier"); | ||
| 32 | } | ||
| 33 | if !f.sig.variadic.is_none() { | ||
| 34 | ctxt.error_spanned_by(&f.sig, "task functions must not be variadic"); | ||
| 35 | } | ||
| 36 | match &f.sig.output { | ||
| 37 | ReturnType::Default => {} | ||
| 38 | ReturnType::Type(_, ty) => match &**ty { | ||
| 39 | Type::Tuple(tuple) if tuple.elems.is_empty() => {} | ||
| 40 | Type::Never(_) => {} | ||
| 41 | _ => ctxt.error_spanned_by( | ||
| 42 | &f.sig, | ||
| 43 | "task functions must either not return a value, return `()` or return `!`", | ||
| 44 | ), | ||
| 45 | }, | ||
| 46 | } | ||
| 47 | |||
| 27 | if pool_size < 1 { | 48 | if pool_size < 1 { |
| 28 | ctxt.error_spanned_by(&f.sig, "pool_size must be 1 or greater"); | 49 | ctxt.error_spanned_by(&f.sig, "pool_size must be 1 or greater"); |
| 29 | } | 50 | } |
