From f74f38a4f764fd017812ff351906b64cbb239767 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jan 2024 08:03:49 +0100 Subject: Update syn requirement from 1.0.107 to 2.0.48 (#881) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update syn requirement from 1.0.107 to 2.0.48 Updates the requirements on [syn](https://github.com/dtolnay/syn) to permit the latest version. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.107...2.0.48) --- updated-dependencies: - dependency-name: syn dependency-type: direct:production ... Signed-off-by: dependabot[bot] * rtic-macros: attr.path -> attr.path() * rtic-macros: tokens -> parse_args() Fix parsing of InitArgs, IdleArgs, *Args Including HardwareTaskArgs, SoftwareTaskArgs * rtic-macros: Rename content to input As syn2 removes the surrounding parenthesis as part of parse_args() the distinction between input and content is redundant * rtic-macros: Handle removal of Expr::Type Manually parse local_resources With type ascription de-RFCd syn2 dropped Expr::Type * rtic-macros: Syn upgrade CHANGELOG * rtic-macro: Retain most old errors as they were Spans are not equal, but good enough * rtic-macros: syn2 changed some error messages Additionally some spans were not retained with the manual parsing workaround * rtic-macros: clippy fixes --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Henrik Tjäder --- rtic-macros/src/codegen/local_resources.rs | 5 +- rtic-macros/src/codegen/shared_resources.rs | 5 +- rtic-macros/src/syntax/parse.rs | 53 ++++---- rtic-macros/src/syntax/parse/app.rs | 25 +++- rtic-macros/src/syntax/parse/init.rs | 3 +- rtic-macros/src/syntax/parse/util.rs | 193 +++++++++++++++++----------- 6 files changed, 171 insertions(+), 113 deletions(-) (limited to 'rtic-macros/src') diff --git a/rtic-macros/src/codegen/local_resources.rs b/rtic-macros/src/codegen/local_resources.rs index e6d1553..c73ad56 100644 --- a/rtic-macros/src/codegen/local_resources.rs +++ b/rtic-macros/src/codegen/local_resources.rs @@ -19,7 +19,10 @@ pub fn codegen(app: &App, _analysis: &Analysis) -> TokenStream2 { // late resources in `util::link_section_uninit` // unless user specifies custom link section - let section = if attrs.iter().any(|attr| attr.path.is_ident("link_section")) { + let section = if attrs + .iter() + .any(|attr| attr.path().is_ident("link_section")) + { None } else { Some(util::link_section_uninit()) diff --git a/rtic-macros/src/codegen/shared_resources.rs b/rtic-macros/src/codegen/shared_resources.rs index 686c280..d89f0c2 100644 --- a/rtic-macros/src/codegen/shared_resources.rs +++ b/rtic-macros/src/codegen/shared_resources.rs @@ -19,7 +19,10 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { // late resources in `util::link_section_uninit` // unless user specifies custom link section - let section = if attrs.iter().any(|attr| attr.path.is_ident("link_section")) { + let section = if attrs + .iter() + .any(|attr| attr.path().is_ident("link_section")) + { None } else { Some(util::link_section_uninit()) diff --git a/rtic-macros/src/syntax/parse.rs b/rtic-macros/src/syntax/parse.rs index 823bd82..aae8a50 100644 --- a/rtic-macros/src/syntax/parse.rs +++ b/rtic-macros/src/syntax/parse.rs @@ -8,7 +8,7 @@ mod util; use proc_macro2::TokenStream as TokenStream2; use syn::{ - braced, parenthesized, + braced, parse::{self, Parse, ParseStream, Parser}, token::Brace, Ident, Item, LitInt, Token, @@ -70,15 +70,12 @@ fn init_args(tokens: TokenStream2) -> parse::Result { let mut local_resources = None; - let content; - parenthesized!(content in input); - - if !content.is_empty() { + if !input.is_empty() { loop { // Parse identifier name - let ident: Ident = content.parse()?; + let ident: Ident = input.parse()?; // Handle equal sign - let _: Token![=] = content.parse()?; + let _: Token![=] = input.parse()?; match &*ident.to_string() { "local" => { @@ -89,18 +86,18 @@ fn init_args(tokens: TokenStream2) -> parse::Result { )); } - local_resources = Some(util::parse_local_resources(&content)?); + local_resources = Some(util::parse_local_resources(input)?); } _ => { return Err(parse::Error::new(ident.span(), "unexpected argument")); } } - if content.is_empty() { + if input.is_empty() { break; } // Handle comma: , - let _: Token![,] = content.parse()?; + let _: Token![,] = input.parse()?; } } @@ -131,14 +128,12 @@ fn idle_args(tokens: TokenStream2) -> parse::Result { let mut shared_resources = None; let mut local_resources = None; - let content; - parenthesized!(content in input); - if !content.is_empty() { + if !input.is_empty() { loop { // Parse identifier name - let ident: Ident = content.parse()?; + let ident: Ident = input.parse()?; // Handle equal sign - let _: Token![=] = content.parse()?; + let _: Token![=] = input.parse()?; match &*ident.to_string() { "shared" => { @@ -149,7 +144,7 @@ fn idle_args(tokens: TokenStream2) -> parse::Result { )); } - shared_resources = Some(util::parse_shared_resources(&content)?); + shared_resources = Some(util::parse_shared_resources(input)?); } "local" => { @@ -160,19 +155,19 @@ fn idle_args(tokens: TokenStream2) -> parse::Result { )); } - local_resources = Some(util::parse_local_resources(&content)?); + local_resources = Some(util::parse_local_resources(input)?); } _ => { return Err(parse::Error::new(ident.span(), "unexpected argument")); } } - if content.is_empty() { + if input.is_empty() { break; } // Handle comma: , - let _: Token![,] = content.parse()?; + let _: Token![,] = input.parse()?; } } @@ -196,19 +191,17 @@ fn task_args(tokens: TokenStream2) -> parse::Result { @@ -220,7 +213,7 @@ fn task_args(tokens: TokenStream2) -> parse::Result parse::Result parse::Result { @@ -274,7 +267,7 @@ fn task_args(tokens: TokenStream2) -> parse::Result { @@ -282,12 +275,12 @@ fn task_args(tokens: TokenStream2) -> parse::Result { check_binding(&args.binds)?; check_ident(&item.sig.ident)?; @@ -369,8 +375,9 @@ impl App { .iter() .position(|attr| util::attr_eq(attr, "init")) { - let args = InitArgs::parse(item.attrs.remove(pos).tokens)?; - + let args = InitArgs::parse( + item.attrs.remove(pos).parse_args().unwrap_or_default(), + )?; // If an init function already exists, error if init.is_some() { return Err(parse::Error::new( @@ -387,7 +394,9 @@ impl App { .iter() .position(|attr| util::attr_eq(attr, "idle")) { - let args = IdleArgs::parse(item.attrs.remove(pos).tokens)?; + let args = IdleArgs::parse( + item.attrs.remove(pos).parse_args().unwrap_or_default(), + )?; // If an idle function already exists, error if idle.is_some() { @@ -421,7 +430,9 @@ impl App { )); } - match syntax_parse::task_args(item.attrs.remove(pos).tokens)? { + match syntax_parse::task_args( + item.attrs.remove(pos).parse_args().unwrap_or_default(), + )? { Either::Left(args) => { check_binding(&args.binds)?; check_ident(&item.sig.ident)?; diff --git a/rtic-macros/src/syntax/parse/init.rs b/rtic-macros/src/syntax/parse/init.rs index 59d0093..e96d5f9 100644 --- a/rtic-macros/src/syntax/parse/init.rs +++ b/rtic-macros/src/syntax/parse/init.rs @@ -1,5 +1,4 @@ -use proc_macro2::TokenStream as TokenStream2; - +use crate::syntax::TokenStream2; use syn::{parse, ForeignItemFn, ItemFn, Stmt}; use crate::syntax::{ diff --git a/rtic-macros/src/syntax/parse/util.rs b/rtic-macros/src/syntax/parse/util.rs index 5a5e0c0..44d9759 100644 --- a/rtic-macros/src/syntax/parse/util.rs +++ b/rtic-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, ExprPath, FnArg, ForeignItemFn, Ident, ItemFn, Pat, PatType, + Path, PathArguments, ReturnType, Token, Type, Visibility, }; use crate::syntax::{ @@ -20,8 +20,8 @@ pub fn abi_is_rust(abi: &Abi) -> bool { } pub fn attr_eq(attr: &Attribute, name: &str) -> bool { - attr.style == AttrStyle::Outer && attr.path.segments.len() == 1 && { - let segment = attr.path.segments.first().unwrap(); + attr.style == AttrStyle::Outer && attr.path().segments.len() == 1 && { + let segment = attr.path().segments.first().unwrap(); segment.arguments == PathArguments::None && *segment.ident.to_string() == *name } } @@ -143,91 +143,140 @@ fn extract_resource_name_ident(path: Path) -> parse::Result { } pub fn parse_local_resources(content: ParseStream<'_>) -> parse::Result { - let inner; - bracketed!(inner in content); + let input; + bracketed!(input in content); let mut resources = Map::new(); - for e in inner.call(Punctuated::::parse_terminated)? { - let err = Err(parse::Error::new( - e.span(), - "identifier appears more than once in list", - )); + let error_msg_no_local_resources = + "malformed, expected 'local = [EXPRPATH: TYPE = EXPR]', or 'local = [EXPRPATH, ...]'"; - let (name, local) = match e { - // local = [IDENT], - Expr::Path(path) => { - if !path.attrs.is_empty() { - return Err(parse::Error::new( - path.span(), - "attributes are not supported here", - )); - } + loop { + if input.is_empty() { + break; + } + // Type ascription is de-RFCd from Rust in + // https://github.com/rust-lang/rfcs/pull/3307 + // Manually pull out the tokens + + // Two acceptable variants: + // + // Task local and declared (initialized in place) + // local = [EXPRPATH: TYPE = EXPR, ...] + // ~~~~~~~~~~~~~~~~~~~~~~ + // or + // Task local but not initialized + // local = [EXPRPATH, ...], + // ~~~~~~~~~ + + // Common: grab first identifier EXPRPATH + // local = [EXPRPATH: TYPE = EXPR, ...] + // ~~~~~~~~ + let exprpath: ExprPath = input.parse()?; + + let name = extract_resource_name_ident(exprpath.path)?; + + // Extract attributes + let ExprPath { attrs, .. } = exprpath; + let (cfgs, attrs) = { + let FilterAttrs { cfgs, attrs, .. } = filter_attributes(attrs); + (cfgs, attrs) + }; - let ident = extract_resource_name_ident(path.path)?; - // let (cfgs, attrs) = extract_cfgs(path.attrs); + let local; - (ident, TaskLocal::External) + // Declared requries type ascription + if input.peek(Token![:]) { + // Handle colon + let _: Token![:] = input.parse()?; + + // Extract the type + let ty: Box = input.parse()?; + + if input.peek(Token![=]) { + // Handle equal sign + let _: Token![=] = input.parse()?; + } else { + return Err(parse::Error::new( + name.span(), + "malformed, expected 'IDENT: TYPE = EXPR'", + )); } - // local = [IDENT: TYPE = EXPR] - Expr::Assign(e) => { - let (name, ty, cfgs, attrs) = match *e.left { - Expr::Type(t) => { - // Extract name and attributes - let (name, cfgs, attrs) = match *t.expr { - Expr::Path(path) => { - let name = extract_resource_name_ident(path.path)?; - let FilterAttrs { cfgs, attrs, .. } = filter_attributes(path.attrs); - - (name, cfgs, attrs) - } - _ => return err, - }; - - let ty = t.ty; - - // Error check - match &*ty { - Type::Array(_) => {} - Type::Path(_) => {} - Type::Ptr(_) => {} - Type::Tuple(_) => {} - _ => return Err(parse::Error::new( - ty.span(), - "unsupported type, must be an array, tuple, pointer or type path", - )), - }; - - (name, ty, cfgs, attrs) - } - e => return Err(parse::Error::new(e.span(), "malformed, expected a type")), - }; - - let expr = e.right; // Expr - - ( - name, - TaskLocal::Declared(Local { - attrs, - cfgs, - ty, - expr, - }), - ) + // Grab the final expression right of equal + let expr: Box = input.parse()?; + + // We got a trailing colon, remove it + if input.peek(Token![,]) { + let _: Token![,] = input.parse()?; } - expr => { + // Error check + match &*ty { + Type::Array(_) => {} + Type::Path(_) => {} + Type::Ptr(_) => {} + Type::Tuple(_) => {} + _ => { + return Err(parse::Error::new( + ty.span(), + "unsupported type, must be an array, tuple, pointer or type path", + )) + } + }; + + local = TaskLocal::Declared(Local { + attrs, + cfgs, + ty, + expr, + }); + } else if input.peek(Token![=]) { + // Missing type ascription is not valid + return Err(parse::Error::new(name.span(), "malformed, expected a type")); + } else if input.peek(Token![,]) { + // Attributes not supported on non-initialized local resources! + + if !attrs.is_empty() { return Err(parse::Error::new( - expr.span(), - "malformed, expected 'IDENT: TYPE = EXPR'", - )) + name.span(), + "attributes are not supported here", + )); } + + // Remove comma + let _: Token![,] = input.parse()?; + + // Expected when multiple local resources + local = TaskLocal::External; + } else if input.is_empty() { + // There was only one single local resource + // Task local but not initialized + // local = [EXPRPATH], + // ~~~~~~~~ + local = TaskLocal::External; + } else { + // Specifying local without any resources is invalid + return Err(parse::Error::new(name.span(), error_msg_no_local_resources)); }; + if resources.contains_key(&name) { + return Err(parse::Error::new( + name.span(), + "resource appears more than once in list", + )); + } + resources.insert(name, local); } + if resources.is_empty() { + return Err(parse::Error::new( + input.span(), + error_msg_no_local_resources, + )); + } + Ok(resources) } -- cgit v1.2.3