aboutsummaryrefslogtreecommitdiff
path: root/macros/src/syntax
diff options
context:
space:
mode:
Diffstat (limited to 'macros/src/syntax')
-rw-r--r--macros/src/syntax/analyze.rs57
-rw-r--r--macros/src/syntax/ast.rs50
-rw-r--r--macros/src/syntax/parse.rs121
-rw-r--r--macros/src/syntax/parse/app.rs58
-rw-r--r--macros/src/syntax/parse/hardware_task.rs44
-rw-r--r--macros/src/syntax/parse/idle.rs18
-rw-r--r--macros/src/syntax/parse/init.rs22
-rw-r--r--macros/src/syntax/parse/software_task.rs26
-rw-r--r--macros/src/syntax/parse/util.rs26
9 files changed, 75 insertions, 347 deletions
diff --git a/macros/src/syntax/analyze.rs b/macros/src/syntax/analyze.rs
index 44960b9e..ff0577da 100644
--- a/macros/src/syntax/analyze.rs
+++ b/macros/src/syntax/analyze.rs
@@ -16,19 +16,11 @@ pub(crate) fn app(app: &App) -> Result<Analysis, syn::Error> {
type TaskName = String;
type Priority = u8;
- // The task list is a Tuple (Name, Shared Resources, Local Resources, Priority, IsAsync)
- let task_resources_list: Vec<(TaskName, Vec<&Ident>, &LocalResources, Priority, bool)> =
+ // The task list is a Tuple (Name, Shared Resources, Local Resources, Priority)
+ let task_resources_list: Vec<(TaskName, Vec<&Ident>, &LocalResources, Priority)> =
Some(&app.init)
.iter()
- .map(|ht| {
- (
- "init".to_string(),
- Vec::new(),
- &ht.args.local_resources,
- 0,
- false,
- )
- })
+ .map(|ht| ("init".to_string(), Vec::new(), &ht.args.local_resources, 0))
.chain(app.idle.iter().map(|ht| {
(
"idle".to_string(),
@@ -39,7 +31,6 @@ pub(crate) fn app(app: &App) -> Result<Analysis, syn::Error> {
.collect::<Vec<_>>(),
&ht.args.local_resources,
0,
- false,
)
}))
.chain(app.software_tasks.iter().map(|(name, ht)| {
@@ -52,7 +43,6 @@ pub(crate) fn app(app: &App) -> Result<Analysis, syn::Error> {
.collect::<Vec<_>>(),
&ht.args.local_resources,
ht.args.priority,
- ht.is_async,
)
}))
.chain(app.hardware_tasks.iter().map(|(name, ht)| {
@@ -65,7 +55,6 @@ pub(crate) fn app(app: &App) -> Result<Analysis, syn::Error> {
.collect::<Vec<_>>(),
&ht.args.local_resources,
ht.args.priority,
- false,
)
}))
.collect();
@@ -84,21 +73,20 @@ pub(crate) fn app(app: &App) -> Result<Analysis, syn::Error> {
// Check that lock_free resources are correct
for lf_res in lock_free.iter() {
- for (task, tr, _, priority, is_async) in task_resources_list.iter() {
+ for (task, tr, _, priority) in task_resources_list.iter() {
for r in tr {
// Get all uses of resources annotated lock_free
if lf_res == r {
// lock_free resources are not allowed in async tasks
- if *is_async {
- error.push(syn::Error::new(
+ error.push(syn::Error::new(
r.span(),
format!(
"Lock free shared resource {:?} is used by an async tasks, which is forbidden",
r.to_string(),
),
));
- }
+ // TODO: Should this be removed?
// HashMap returns the previous existing object if old.key == new.key
if let Some(lf_res) = lf_hash.insert(r.to_string(), (task, r, priority)) {
// Check if priority differ, if it does, append to
@@ -150,7 +138,7 @@ pub(crate) fn app(app: &App) -> Result<Analysis, syn::Error> {
// Check that local resources are not shared
for lr in local {
- for (task, _, local_resources, _, _) in task_resources_list.iter() {
+ for (task, _, local_resources, _) in task_resources_list.iter() {
for (name, res) in local_resources.iter() {
// Get all uses of resources annotated lock_free
if lr == name {
@@ -193,18 +181,7 @@ pub(crate) fn app(app: &App) -> Result<Analysis, syn::Error> {
error.push(syn::Error::new(
name.span(),
format!(
- "Software task {:?} has priority 0, but `#[idle]` is defined. 0-priority software tasks are only allowed if there is no `#[idle]`.",
- name.to_string(),
- )
- ));
- }
-
- // 0-priority tasks must be async
- if !task.is_async {
- error.push(syn::Error::new(
- name.span(),
- format!(
- "Software task {:?} has priority 0, but is not `async`. 0-priority software tasks must be `async`.",
+ "Async task {:?} has priority 0, but `#[idle]` is defined. 0-priority async tasks are only allowed if there is no `#[idle]`.",
name.to_string(),
)
));
@@ -263,7 +240,7 @@ pub(crate) fn app(app: &App) -> Result<Analysis, syn::Error> {
// Create the list of used local resource Idents
let mut used_local_resource = IndexSet::new();
- for (_, _, locals, _, _) in task_resources_list {
+ for (_, _, locals, _) in task_resources_list {
for (local, _) in locals {
used_local_resource.insert(local.clone());
}
@@ -307,27 +284,11 @@ pub(crate) fn app(app: &App) -> Result<Analysis, syn::Error> {
let channel = channels.entry(spawnee_prio).or_default();
channel.tasks.insert(name.clone());
-
- if !spawnee.args.only_same_priority_spawn {
- // Require `Send` if the task can be spawned from other priorities
- spawnee.inputs.iter().for_each(|input| {
- send_types.insert(input.ty.clone());
- });
- }
}
// No channel should ever be empty
debug_assert!(channels.values().all(|channel| !channel.tasks.is_empty()));
- // Compute channel capacities
- for channel in channels.values_mut() {
- channel.capacity = channel
- .tasks
- .iter()
- .map(|name| app.software_tasks[name].args.capacity)
- .sum();
- }
-
Ok(Analysis {
channels,
shared_resources: used_shared_resource,
diff --git a/macros/src/syntax/ast.rs b/macros/src/syntax/ast.rs
index 0f2e36f4..ea6e402c 100644
--- a/macros/src/syntax/ast.rs
+++ b/macros/src/syntax/ast.rs
@@ -1,6 +1,6 @@
//! Abstract Syntax Tree
-use syn::{Attribute, Expr, Ident, Item, ItemUse, Pat, PatType, Path, Stmt, Type};
+use syn::{Attribute, Expr, Ident, Item, ItemUse, Pat, Path, Stmt, Type};
use crate::syntax::Map;
@@ -20,9 +20,6 @@ pub struct App {
/// The `#[idle]` function
pub idle: Option<Idle>,
- /// Monotonic clocks
- pub monotonics: Map<Monotonic>,
-
/// Resources shared between tasks defined in `#[shared]`
pub shared_resources: Map<SharedResource>,
@@ -38,7 +35,7 @@ pub struct App {
/// Hardware tasks: `#[task(binds = ..)]`s
pub hardware_tasks: Map<HardwareTask>,
- /// Software tasks: `#[task]`
+ /// Async software tasks: `#[task]`
pub software_tasks: Map<SoftwareTask>,
}
@@ -192,38 +189,7 @@ pub struct LocalResource {
pub ty: Box<Type>,
}
-/// Monotonic
-#[derive(Debug)]
-#[non_exhaustive]
-pub struct Monotonic {
- /// `#[cfg]` attributes like `#[cfg(debug_assertions)]`
- pub cfgs: Vec<Attribute>,
-
- /// The identifier of the monotonic
- pub ident: Ident,
-
- /// The type of this monotonic
- pub ty: Box<Type>,
-
- /// Monotonic args
- pub args: MonotonicArgs,
-}
-
-/// Monotonic metadata
-#[derive(Debug)]
-#[non_exhaustive]
-pub struct MonotonicArgs {
- /// The interrupt or exception that this monotonic is bound to
- pub binds: Ident,
-
- /// The priority of this monotonic
- pub priority: Option<u8>,
-
- /// If this is the default monotonic
- pub default: bool,
-}
-
-/// A software task
+/// An async software task
#[derive(Debug)]
#[non_exhaustive]
pub struct SoftwareTask {
@@ -239,26 +205,17 @@ pub struct SoftwareTask {
/// The context argument
pub context: Box<Pat>,
- /// The inputs of this software task
- pub inputs: Vec<PatType>,
-
/// The statements that make up the task handler
pub stmts: Vec<Stmt>,
/// The task is declared externally
pub is_extern: bool,
-
- /// If the task is marked as `async`
- pub is_async: bool,
}
/// Software task metadata
#[derive(Debug)]
#[non_exhaustive]
pub struct SoftwareTaskArgs {
- /// The task capacity: the maximum number of pending messages that can be queued
- pub capacity: u8,
-
/// The priority of this task
pub priority: u8,
@@ -275,7 +232,6 @@ pub struct SoftwareTaskArgs {
impl Default for SoftwareTaskArgs {
fn default() -> Self {
Self {
- capacity: 1,
priority: 1,
local_resources: LocalResources::new(),
shared_resources: SharedResources::new(),
diff --git a/macros/src/syntax/parse.rs b/macros/src/syntax/parse.rs
index ceedaa98..abdd677a 100644
--- a/macros/src/syntax/parse.rs
+++ b/macros/src/syntax/parse.rs
@@ -2,7 +2,6 @@ mod app;
mod hardware_task;
mod idle;
mod init;
-mod monotonic;
mod resource;
mod software_task;
mod util;
@@ -11,15 +10,12 @@ use proc_macro2::TokenStream as TokenStream2;
use syn::{
braced, parenthesized,
parse::{self, Parse, ParseStream, Parser},
- token::{self, Brace},
- Ident, Item, LitBool, LitInt, Path, Token,
+ token::Brace,
+ Ident, Item, LitInt, Token,
};
use crate::syntax::{
- ast::{
- App, AppArgs, HardwareTaskArgs, IdleArgs, InitArgs, MonotonicArgs, SoftwareTaskArgs,
- TaskLocal,
- },
+ ast::{App, AppArgs, HardwareTaskArgs, IdleArgs, InitArgs, SoftwareTaskArgs, TaskLocal},
Either,
};
@@ -388,7 +384,6 @@ fn task_args(tokens: TokenStream2) -> parse::Result<Either<HardwareTaskArgs, Sof
})
} else {
Either::Right(SoftwareTaskArgs {
- capacity: capacity.unwrap_or(1),
priority,
shared_resources,
local_resources,
@@ -398,113 +393,3 @@ fn task_args(tokens: TokenStream2) -> parse::Result<Either<HardwareTaskArgs, Sof
})
.parse2(tokens)
}
-
-fn monotonic_args(path: Path, tokens: TokenStream2) -> parse::Result<MonotonicArgs> {
- (|input: ParseStream<'_>| -> parse::Result<MonotonicArgs> {
- let mut binds = None;
- let mut priority = None;
- let mut default = None;
-
- if !input.peek(token::Paren) {
- return Err(parse::Error::new(
- path.segments.first().unwrap().ident.span(),
- "expected opening ( in #[monotonic( ... )]",
- ));
- }
-
- let content;
- parenthesized!(content in input);
-
- if !content.is_empty() {
- loop {
- // Parse identifier name
- let ident: Ident = content.parse()?;
- // Handle equal sign
- let _: Token![=] = content.parse()?;
-
- match &*ident.to_string() {
- "binds" => {
- if binds.is_some() {
- return Err(parse::Error::new(
- ident.span(),
- "argument appears more than once",
- ));
- }
- // Parse identifier name
- let ident = content.parse()?;
-
- binds = Some(ident);
- }
-
- "priority" => {
- if priority.is_some() {
- return Err(parse::Error::new(
- ident.span(),
- "argument appears more than once",
- ));
- }
-
- // #lit
- let lit: LitInt = content.parse()?;
-
- if !lit.suffix().is_empty() {
- return Err(parse::Error::new(
- lit.span(),
- "this literal must be unsuffixed",
- ));
- }
-
- let value = lit.base10_parse::<u8>().ok();
- if value.is_none() || value == Some(0) {
- return Err(parse::Error::new(
- lit.span(),
- "this literal must be in the range 1...255",
- ));
- }
-
- priority = Some(value.unwrap());
- }
-
- "default" => {
- if default.is_some() {
- return Err(parse::Error::new(
- ident.span(),
- "argument appears more than once",
- ));
- }
-
- let lit: LitBool = content.parse()?;
- default = Some(lit.value);
- }
-
- _ => {
- return Err(parse::Error::new(ident.span(), "unexpected argument"));
- }
- }
- if content.is_empty() {
- break;
- }
-
- // Handle comma: ,
- let _: Token![,] = content.parse()?;
- }
- }
-
- let binds = if let Some(r) = binds {
- r
- } else {
- return Err(parse::Error::new(
- content.span(),
- "`binds = ...` is missing",
- ));
- };
- let default = default.unwrap_or(false);
-
- Ok(MonotonicArgs {
- binds,
- priority,
- default,
- })
- })
- .parse2(tokens)
-}
diff --git a/macros/src/syntax/parse/app.rs b/macros/src/syntax/parse/app.rs
index dd7c3999..8a9242e9 100644
--- a/macros/src/syntax/parse/app.rs
+++ b/macros/src/syntax/parse/app.rs
@@ -5,14 +5,14 @@ use proc_macro2::TokenStream as TokenStream2;
use syn::{
parse::{self, ParseStream, Parser},
spanned::Spanned,
- Expr, ExprArray, Fields, ForeignItem, Ident, Item, LitBool, Path, Token, Type, Visibility,
+ Expr, ExprArray, Fields, ForeignItem, Ident, Item, LitBool, Path, Token, Visibility,
};
use super::Input;
use crate::syntax::{
ast::{
App, AppArgs, Dispatcher, Dispatchers, HardwareTask, Idle, IdleArgs, Init, InitArgs,
- LocalResource, Monotonic, MonotonicArgs, SharedResource, SoftwareTask,
+ LocalResource, SharedResource, SoftwareTask,
},
parse::{self as syntax_parse, util},
Either, Map, Set,
@@ -150,7 +150,6 @@ impl App {
let mut shared_resources = Map::new();
let mut local_resources_ident = None;
let mut local_resources = Map::new();
- let mut monotonics = Map::new();
let mut hardware_tasks = Map::new();
let mut software_tasks = Map::new();
let mut user_imports = vec![];
@@ -158,7 +157,6 @@ impl App {
let mut seen_idents = HashSet::<Ident>::new();
let mut bindings = HashSet::<Ident>::new();
- let mut monotonic_types = HashSet::<Type>::new();
let mut check_binding = |ident: &Ident| {
if bindings.contains(ident) {
@@ -186,19 +184,6 @@ impl App {
Ok(())
};
- let mut check_monotonic = |ty: &Type| {
- if monotonic_types.contains(ty) {
- return Err(parse::Error::new(
- ty.span(),
- "this type is already used by another monotonic",
- ));
- } else {
- monotonic_types.insert(ty.clone());
- }
-
- Ok(())
- };
-
for mut item in input.items {
match item {
Item::Fn(mut item) => {
@@ -448,44 +433,6 @@ impl App {
// Store the user provided use-statements
user_imports.push(itemuse_.clone());
}
- Item::Type(ref mut type_item) => {
- // Match types with the attribute #[monotonic]
- if let Some(pos) = type_item
- .attrs
- .iter()
- .position(|attr| util::attr_eq(attr, "monotonic"))
- {
- let span = type_item.ident.span();
-
- if monotonics.contains_key(&type_item.ident) {
- return Err(parse::Error::new(
- span,
- "`#[monotonic(...)]` on a specific type must appear at most once",
- ));
- }
-
- if type_item.vis != Visibility::Inherited {
- return Err(parse::Error::new(
- type_item.span(),
- "this item must have inherited / private visibility",
- ));
- }
-
- check_monotonic(&*type_item.ty)?;
-
- let m = type_item.attrs.remove(pos);
- let args = MonotonicArgs::parse(m)?;
-
- check_binding(&args.binds)?;
-
- let monotonic = Monotonic::parse(args, type_item, span)?;
-
- monotonics.insert(type_item.ident.clone(), monotonic);
- }
-
- // All types are passed on
- user_code.push(item.clone());
- }
_ => {
// Anything else within the module should not make any difference
user_code.push(item.clone());
@@ -524,7 +471,6 @@ impl App {
name: input.ident,
init,
idle,
- monotonics,
shared_resources,
local_resources,
user_imports,
diff --git a/macros/src/syntax/parse/hardware_task.rs b/macros/src/syntax/parse/hardware_task.rs
index 304bfcd3..ff94bc51 100644
--- a/macros/src/syntax/parse/hardware_task.rs
+++ b/macros/src/syntax/parse/hardware_task.rs
@@ -23,19 +23,17 @@ impl HardwareTask {
}
if valid_signature {
- if let Some((context, Ok(rest))) = util::parse_inputs(item.sig.inputs, &name) {
- if rest.is_empty() {
- let FilterAttrs { cfgs, attrs, .. } = util::filter_attributes(item.attrs);
+ if let Some(context) = util::parse_inputs(item.sig.inputs, &name) {
+ let FilterAttrs { cfgs, attrs, .. } = util::filter_attributes(item.attrs);
- return Ok(HardwareTask {
- args,
- cfgs,
- attrs,
- context,
- stmts: item.block.stmts,
- is_extern: false,
- });
- }
+ return Ok(HardwareTask {
+ args,
+ cfgs,
+ attrs,
+ context,
+ stmts: item.block.stmts,
+ is_extern: false,
+ });
}
}
@@ -69,19 +67,17 @@ impl HardwareTask {
}
if valid_signature {
- if let Some((context, Ok(rest))) = util::parse_inputs(item.sig.inputs, &name) {
- if rest.is_empty() {
- let FilterAttrs { cfgs, attrs, .. } = util::filter_attributes(item.attrs);
+ if let Some(context) = util::parse_inputs(item.sig.inputs, &name) {
+ let FilterAttrs { cfgs, attrs, .. } = util::filter_attributes(item.attrs);
- return Ok(HardwareTask {
- args,
- cfgs,
- attrs,
- context,
- stmts: Vec::<Stmt>::new(),
- is_extern: true,
- });
- }
+ return Ok(HardwareTask {
+ args,
+ cfgs,
+ attrs,
+ context,
+ stmts: Vec::<Stmt>::new(),
+ is_extern: true,
+ });
}
}
diff --git a/macros/src/syntax/parse/idle.rs b/macros/src/syntax/parse/idle.rs
index d9f3a99e..ffec358f 100644
--- a/macros/src/syntax/parse/idle.rs
+++ b/macros/src/syntax/parse/idle.rs
@@ -21,16 +21,14 @@ impl Idle {
let name = item.sig.ident.to_string();
if valid_signature {
- if let Some((context, Ok(rest))) = util::parse_inputs(item.sig.inputs, &name) {
- if rest.is_empty() {
- return Ok(Idle {
- args,
- attrs: item.attrs,
- context,
- name: item.sig.ident,
- stmts: item.block.stmts,
- });
- }
+ if let Some(context) = util::parse_inputs(item.sig.inputs, &name) {
+ return Ok(Idle {
+ args,
+ attrs: item.attrs,
+ context,
+ name: item.sig.ident,
+ stmts: item.block.stmts,
+ });
}
}
diff --git a/macros/src/syntax/parse/init.rs b/macros/src/syntax/parse/init.rs
index 727ee205..5ec1abaf 100644
--- a/macros/src/syntax/parse/init.rs
+++ b/macros/src/syntax/parse/init.rs
@@ -25,18 +25,16 @@ impl Init {
if let Ok((user_shared_struct, user_local_struct)) =
util::type_is_init_return(&item.sig.output, &name)
{
- if let Some((context, Ok(rest))) = util::parse_inputs(item.sig.inputs, &name) {
- if rest.is_empty() {
- return Ok(Init {
- args,
- attrs: item.attrs,
- context,
- name: item.sig.ident,
- stmts: item.block.stmts,
- user_shared_struct,
- user_local_struct,
- });
- }
+ if let Some(context) = util::parse_inputs(item.sig.inputs, &name) {
+ return Ok(Init {
+ args,
+ attrs: item.attrs,
+ context,
+ name: item.sig.ident,
+ stmts: item.block.stmts,
+ user_shared_struct,
+ user_local_struct,
+ });
}
}
}
diff --git a/macros/src/syntax/parse/software_task.rs b/macros/src/syntax/parse/software_task.rs
index 2b1ac4a5..6be597e8 100644
--- a/macros/src/syntax/parse/software_task.rs
+++ b/macros/src/syntax/parse/software_task.rs
@@ -8,17 +8,16 @@ use crate::syntax::{
impl SoftwareTask {
pub(crate) fn parse(args: SoftwareTaskArgs, item: ItemFn) -> parse::Result<Self> {
- let valid_signature =
- util::check_fn_signature(&item, true) && util::type_is_unit(&item.sig.output);
+ let valid_signature = util::check_fn_signature(&item, true)
+ && util::type_is_unit(&item.sig.output)
+ && item.sig.asyncness.is_some();
let span = item.sig.ident.span();
let name = item.sig.ident.to_string();
- let is_async = item.sig.asyncness.is_some();
-
if valid_signature {
- if let Some((context, Ok(inputs))) = util::parse_inputs(item.sig.inputs, &name) {
+ if let Some(context) = util::parse_inputs(item.sig.inputs, &name) {
let FilterAttrs { cfgs, attrs, .. } = util::filter_attributes(item.attrs);
return Ok(SoftwareTask {
@@ -26,10 +25,8 @@ impl SoftwareTask {
attrs,
cfgs,
context,
- inputs,
stmts: item.block.stmts,
is_extern: false,
- is_async,
});
}
}
@@ -37,7 +34,7 @@ impl SoftwareTask {
Err(parse::Error::new(
span,
&format!(
- "this task handler must have type signature `(async) fn({}::Context, ..)`",
+ "this task handler must have type signature `async fn({}::Context)`",
name
),
))
@@ -49,17 +46,16 @@ impl SoftwareTask {
args: SoftwareTaskArgs,
item: ForeignItemFn,
) -> parse::Result<Self> {
- let valid_signature =
- util::check_foreign_fn_signature(&item, true) && util::type_is_unit(&item.sig.output);
+ let valid_signature = util::check_foreign_fn_signature(&item, true)
+ && util::type_is_unit(&item.sig.output)
+ && item.sig.asyncness.is_some();
let span = item.sig.ident.span();
let name = item.sig.ident.to_string();
- let is_async = item.sig.asyncness.is_some();
-
if valid_signature {
- if let Some((context, Ok(inputs))) = util::parse_inputs(item.sig.inputs, &name) {
+ if let Some(context) = util::parse_inputs(item.sig.inputs, &name) {
let FilterAttrs { cfgs, attrs, .. } = util::filter_attributes(item.attrs);
return Ok(SoftwareTask {
@@ -67,10 +63,8 @@ impl SoftwareTask {
attrs,
cfgs,
context,
- inputs,
stmts: Vec::<Stmt>::new(),
is_extern: true,
- is_async,
});
}
}
@@ -78,7 +72,7 @@ impl SoftwareTask {
Err(parse::Error::new(
span,
&format!(
- "this task handler must have type signature `(async) fn({}::Context, ..)`",
+ "this task handler must have type signature `async fn({}::Context)`",
name
),
))
diff --git a/macros/src/syntax/parse/util.rs b/macros/src/syntax/parse/util.rs
index 3fa51ef8..119129c0 100644
--- a/macros/src/syntax/parse/util.rs
+++ b/macros/src/syntax/parse/util.rs
@@ -3,8 +3,8 @@ use syn::{
parse::{self, ParseStream},
punctuated::Punctuated,
spanned::Spanned,
- Abi, AttrStyle, Attribute, Expr, FnArg, ForeignItemFn, Ident, ItemFn, Pat, PatType, Path,
- PathArguments, ReturnType, Token, Type, Visibility,
+ Abi, AttrStyle, Attribute, Expr, FnArg, ForeignItemFn, Ident, ItemFn, Pat, Path, PathArguments,
+ ReturnType, Token, Type, Visibility,
};
use crate::syntax::{
@@ -231,29 +231,23 @@ pub fn parse_local_resources(content: ParseStream<'_>) -> parse::Result<LocalRes
Ok(resources)
}
-type ParseInputResult = Option<(Box<Pat>, Result<Vec<PatType>, FnArg>)>;
-
-pub fn parse_inputs(inputs: Punctuated<FnArg, Token![,]>, name: &str) -> ParseInputResult {
+pub fn parse_inputs(inputs: Punctuated<FnArg, Token![,]>, name: &str) -> Option<Box<Pat>> {
let mut inputs = inputs.into_iter();
match inputs.next() {
Some(FnArg::Typed(first)) => {
if type_is_path(&first.ty, &[name, "Context"]) {
- let rest = inputs
- .map(|arg| match arg {
- FnArg::Typed(arg) => Ok(arg),
- _ => Err(arg),
- })
- .collect::<Result<Vec<_>, _>>();
-
- Some((first.pat, rest))
- } else {
- None
+ // No more inputs
+ if inputs.next().is_none() {
+ return Some(first.pat);
+ }
}
}
- _ => None,
+ _ => {}
}
+
+ None
}
pub fn type_is_bottom(ty: &ReturnType) -> bool {