Merge #1267
1267: macros: better validation of function signatures. r=Dirbaio a=Dirbaio Fixes #1266 bors r+ Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
commit
8fd30e407c
@ -1,6 +1,7 @@
|
|||||||
use darling::FromMeta;
|
use darling::FromMeta;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
use syn::{ReturnType, Type};
|
||||||
|
|
||||||
use crate::util::ctxt::Ctxt;
|
use crate::util::ctxt::Ctxt;
|
||||||
|
|
||||||
@ -76,6 +77,26 @@ pub fn run(args: syn::AttributeArgs, f: syn::ItemFn, main: TokenStream) -> Resul
|
|||||||
if !f.sig.generics.params.is_empty() {
|
if !f.sig.generics.params.is_empty() {
|
||||||
ctxt.error_spanned_by(&f.sig, "main function must not be generic");
|
ctxt.error_spanned_by(&f.sig, "main function must not be generic");
|
||||||
}
|
}
|
||||||
|
if !f.sig.generics.where_clause.is_none() {
|
||||||
|
ctxt.error_spanned_by(&f.sig, "main function must not have `where` clauses");
|
||||||
|
}
|
||||||
|
if !f.sig.abi.is_none() {
|
||||||
|
ctxt.error_spanned_by(&f.sig, "main function must not have an ABI qualifier");
|
||||||
|
}
|
||||||
|
if !f.sig.variadic.is_none() {
|
||||||
|
ctxt.error_spanned_by(&f.sig, "main function must not be variadic");
|
||||||
|
}
|
||||||
|
match &f.sig.output {
|
||||||
|
ReturnType::Default => {}
|
||||||
|
ReturnType::Type(_, ty) => match &**ty {
|
||||||
|
Type::Tuple(tuple) if tuple.elems.is_empty() => {}
|
||||||
|
Type::Never(_) => {}
|
||||||
|
_ => ctxt.error_spanned_by(
|
||||||
|
&f.sig,
|
||||||
|
"main function must either not return a value, return `()` or return `!`",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
if fargs.len() != 1 {
|
if fargs.len() != 1 {
|
||||||
ctxt.error_spanned_by(&f.sig, "main function must have 1 argument: the spawner.");
|
ctxt.error_spanned_by(&f.sig, "main function must have 1 argument: the spawner.");
|
||||||
@ -84,10 +105,11 @@ pub fn run(args: syn::AttributeArgs, f: syn::ItemFn, main: TokenStream) -> Resul
|
|||||||
ctxt.check()?;
|
ctxt.check()?;
|
||||||
|
|
||||||
let f_body = f.block;
|
let f_body = f.block;
|
||||||
|
let out = &f.sig.output;
|
||||||
|
|
||||||
let result = quote! {
|
let result = quote! {
|
||||||
#[::embassy_executor::task()]
|
#[::embassy_executor::task()]
|
||||||
async fn __embassy_main(#fargs) {
|
async fn __embassy_main(#fargs) #out {
|
||||||
#f_body
|
#f_body
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use darling::FromMeta;
|
use darling::FromMeta;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use syn::{parse_quote, ItemFn};
|
use syn::{parse_quote, ItemFn, ReturnType, Type};
|
||||||
|
|
||||||
use crate::util::ctxt::Ctxt;
|
use crate::util::ctxt::Ctxt;
|
||||||
|
|
||||||
@ -24,6 +24,27 @@ pub fn run(args: syn::AttributeArgs, f: syn::ItemFn) -> Result<TokenStream, Toke
|
|||||||
if !f.sig.generics.params.is_empty() {
|
if !f.sig.generics.params.is_empty() {
|
||||||
ctxt.error_spanned_by(&f.sig, "task functions must not be generic");
|
ctxt.error_spanned_by(&f.sig, "task functions must not be generic");
|
||||||
}
|
}
|
||||||
|
if !f.sig.generics.where_clause.is_none() {
|
||||||
|
ctxt.error_spanned_by(&f.sig, "task functions must not have `where` clauses");
|
||||||
|
}
|
||||||
|
if !f.sig.abi.is_none() {
|
||||||
|
ctxt.error_spanned_by(&f.sig, "task functions must not have an ABI qualifier");
|
||||||
|
}
|
||||||
|
if !f.sig.variadic.is_none() {
|
||||||
|
ctxt.error_spanned_by(&f.sig, "task functions must not be variadic");
|
||||||
|
}
|
||||||
|
match &f.sig.output {
|
||||||
|
ReturnType::Default => {}
|
||||||
|
ReturnType::Type(_, ty) => match &**ty {
|
||||||
|
Type::Tuple(tuple) if tuple.elems.is_empty() => {}
|
||||||
|
Type::Never(_) => {}
|
||||||
|
_ => ctxt.error_spanned_by(
|
||||||
|
&f.sig,
|
||||||
|
"task functions must either not return a value, return `()` or return `!`",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
if pool_size < 1 {
|
if pool_size < 1 {
|
||||||
ctxt.error_spanned_by(&f.sig, "pool_size must be 1 or greater");
|
ctxt.error_spanned_by(&f.sig, "pool_size must be 1 or greater");
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ const ADDRESS: u8 = 0x5F;
|
|||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) {
|
||||||
info!("Hello world!");
|
info!("Hello world!");
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ use {defmt_rtt as _, panic_probe as _};
|
|||||||
const ALLOW_WRITES: bool = false;
|
const ALLOW_WRITES: bool = false;
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) {
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.rcc.sys_ck = Some(mhz(48));
|
config.rcc.sys_ck = Some(mhz(48));
|
||||||
config.rcc.pll48 = true;
|
config.rcc.pll48 = true;
|
||||||
@ -75,6 +75,4 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
|
|
||||||
sdmmc.read_block(block_idx, &mut block).await.unwrap();
|
sdmmc.read_block(block_idx, &mut block).await.unwrap();
|
||||||
info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]);
|
info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]);
|
||||||
|
|
||||||
loop {}
|
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
let r = socket.write_all(&buf).await;
|
let r = socket.write_all(&buf).await;
|
||||||
if let Err(e) = r {
|
if let Err(e) = r {
|
||||||
info!("write error: {:?}", e);
|
info!("write error: {:?}", e);
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
Timer::after(Duration::from_secs(1)).await;
|
Timer::after(Duration::from_secs(1)).await;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ use embassy_stm32::{interrupt, Config};
|
|||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) {
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.rcc.sys_ck = Some(mhz(200));
|
config.rcc.sys_ck = Some(mhz(200));
|
||||||
config.rcc.pll48 = true;
|
config.rcc.pll48 = true;
|
||||||
@ -41,6 +41,4 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
let card = unwrap!(sdmmc.card());
|
let card = unwrap!(sdmmc.card());
|
||||||
|
|
||||||
info!("Card: {:#?}", Debug2Format(card));
|
info!("Card: {:#?}", Debug2Format(card));
|
||||||
|
|
||||||
loop {}
|
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
let r = socket.write_all(b"Hello\n").await;
|
let r = socket.write_all(b"Hello\n").await;
|
||||||
if let Err(e) = r {
|
if let Err(e) = r {
|
||||||
info!("write error: {:?}", e);
|
info!("write error: {:?}", e);
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
Timer::after(Duration::from_secs(1)).await;
|
Timer::after(Duration::from_secs(1)).await;
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
let r = connection.write_all(b"Hello\n").await;
|
let r = connection.write_all(b"Hello\n").await;
|
||||||
if let Err(e) = r {
|
if let Err(e) = r {
|
||||||
info!("write error: {:?}", e);
|
info!("write error: {:?}", e);
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
Timer::after(Duration::from_secs(1)).await;
|
Timer::after(Duration::from_secs(1)).await;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ const ADDRESS: u8 = 0x5F;
|
|||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) {
|
||||||
info!("Hello world!");
|
info!("Hello world!");
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ const ADDRESS: u8 = 0x5F;
|
|||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let irq = interrupt::take!(I2C2_EV);
|
let irq = interrupt::take!(I2C2_EV);
|
||||||
let mut i2c = I2c::new(
|
let mut i2c = I2c::new(
|
||||||
|
@ -16,7 +16,7 @@ const ADDRESS: u8 = 0x5F;
|
|||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let irq = interrupt::take!(I2C2_EV);
|
let irq = interrupt::take!(I2C2_EV);
|
||||||
let i2c = I2c::new(
|
let i2c = I2c::new(
|
||||||
|
@ -13,7 +13,7 @@ const ADDRESS: u8 = 0x5F;
|
|||||||
const WHOAMI: u8 = 0x0F;
|
const WHOAMI: u8 = 0x0F;
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let irq = interrupt::take!(I2C2_EV);
|
let irq = interrupt::take!(I2C2_EV);
|
||||||
let mut i2c = I2c::new(
|
let mut i2c = I2c::new(
|
||||||
|
Loading…
Reference in New Issue
Block a user