Update syn requirement from 1.0.107 to 2.0.48 (#881)

* 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] <support@github.com>

* 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] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Henrik Tjäder <henrik@tjaders.com>
This commit is contained in:
dependabot[bot] 2024-01-16 08:03:49 +01:00 committed by GitHub
parent c630657009
commit f74f38a4f7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 186 additions and 125 deletions

View file

@ -11,6 +11,10 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!
- Unstable ESP32-C3 support.
### Changed
- Upgraded from syn 1.x to syn 2.x
## [v2.0.1] - 2023-07-25
### Added

View file

@ -46,7 +46,7 @@ indexmap = "2.0.0"
proc-macro2 = "1.0.49"
proc-macro-error = "1.0.4"
quote = "1.0.23"
syn = { version = "1.0.107", features = ["extra-traits", "full"] }
syn = { version = "2.0.48", features = ["extra-traits", "full"] }
[dev-dependencies]
trybuild = "1.0.73"

View file

@ -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())

View file

@ -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())

View file

@ -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<InitArgs> {
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<InitArgs> {
));
}
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<IdleArgs> {
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<IdleArgs> {
));
}
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<IdleArgs> {
));
}
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<Either<HardwareTaskArgs, Sof
let mut local_resources = None;
let mut prio_span = None;
let content;
parenthesized!(content in input);
loop {
if content.is_empty() {
if input.is_empty() {
break;
}
// Parse identifier name
let ident: Ident = content.parse()?;
let ident: Ident = input.parse()?;
let ident_s = ident.to_string();
// Handle equal sign
let _: Token![=] = content.parse()?;
let _: Token![=] = input.parse()?;
match &*ident_s {
"binds" => {
@ -220,7 +213,7 @@ fn task_args(tokens: TokenStream2) -> parse::Result<Either<HardwareTaskArgs, Sof
}
// Parse identifier name
let ident = content.parse()?;
let ident = input.parse()?;
binds = Some(ident);
}
@ -234,7 +227,7 @@ fn task_args(tokens: TokenStream2) -> parse::Result<Either<HardwareTaskArgs, Sof
}
// #lit
let lit: LitInt = content.parse()?;
let lit: LitInt = input.parse()?;
if !lit.suffix().is_empty() {
return Err(parse::Error::new(
@ -263,7 +256,7 @@ fn task_args(tokens: TokenStream2) -> parse::Result<Either<HardwareTaskArgs, Sof
));
}
shared_resources = Some(util::parse_shared_resources(&content)?);
shared_resources = Some(util::parse_shared_resources(input)?);
}
"local" => {
@ -274,7 +267,7 @@ fn task_args(tokens: TokenStream2) -> parse::Result<Either<HardwareTaskArgs, Sof
));
}
local_resources = Some(util::parse_local_resources(&content)?);
local_resources = Some(util::parse_local_resources(input)?);
}
_ => {
@ -282,12 +275,12 @@ fn task_args(tokens: TokenStream2) -> parse::Result<Either<HardwareTaskArgs, Sof
}
}
if content.is_empty() {
if input.is_empty() {
break;
}
// Handle comma: ,
let _: Token![,] = content.parse()?;
let _: Token![,] = input.parse()?;
}
let shared_resources = shared_resources.unwrap_or_default();
let local_resources = local_resources.unwrap_or_default();

View file

@ -198,7 +198,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() {
@ -216,7 +218,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() {
@ -243,7 +247,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)?;
@ -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)?;

View file

@ -1,5 +1,4 @@
use proc_macro2::TokenStream as TokenStream2;
use crate::syntax::TokenStream2;
use syn::{parse, ForeignItemFn, ItemFn, Stmt};
use crate::syntax::{

View file

@ -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,49 +143,73 @@ fn extract_resource_name_ident(path: Path) -> parse::Result<Ident> {
}
pub fn parse_local_resources(content: ParseStream<'_>) -> parse::Result<LocalResources> {
let inner;
bracketed!(inner in content);
let input;
bracketed!(input in content);
let mut resources = Map::new();
for e in inner.call(Punctuated::<Expr, Token![,]>::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
let ident = extract_resource_name_ident(path.path)?;
// let (cfgs, attrs) = extract_cfgs(path.attrs);
// Two acceptable variants:
//
// Task local and declared (initialized in place)
// local = [EXPRPATH: TYPE = EXPR, ...]
// ~~~~~~~~~~~~~~~~~~~~~~
// or
// Task local but not initialized
// local = [EXPRPATH, ...],
// ~~~~~~~~~
(ident, TaskLocal::External)
}
// Common: grab first identifier EXPRPATH
// local = [EXPRPATH: TYPE = EXPR, ...]
// ~~~~~~~~
let exprpath: ExprPath = input.parse()?;
// 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);
let name = extract_resource_name_ident(exprpath.path)?;
(name, cfgs, attrs)
}
_ => return err,
// Extract attributes
let ExprPath { attrs, .. } = exprpath;
let (cfgs, attrs) = {
let FilterAttrs { cfgs, attrs, .. } = filter_attributes(attrs);
(cfgs, attrs)
};
let ty = t.ty;
let local;
// Declared requries type ascription
if input.peek(Token![:]) {
// Handle colon
let _: Token![:] = input.parse()?;
// Extract the type
let ty: Box<Type> = 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'",
));
}
// Grab the final expression right of equal
let expr: Box<Expr> = input.parse()?;
// We got a trailing colon, remove it
if input.peek(Token![,]) {
let _: Token![,] = input.parse()?;
}
// Error check
match &*ty {
@ -193,41 +217,66 @@ pub fn parse_local_resources(content: ParseStream<'_>) -> parse::Result<LocalRes
Type::Path(_) => {}
Type::Ptr(_) => {}
Type::Tuple(_) => {}
_ => return Err(parse::Error::new(
_ => {
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,
}),
)
}
expr => {
return Err(parse::Error::new(
expr.span(),
"malformed, expected 'IDENT: TYPE = EXPR'",
))
}
};
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(
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)
}

View file

@ -1,4 +1,4 @@
error: unexpected end of input, expected one of: `for`, parentheses, `fn`, `unsafe`, `extern`, identifier, `::`, `<`, square brackets, `*`, `&`, `!`, `impl`, `_`, lifetime
error: unexpected end of input, expected one of: `for`, parentheses, `fn`, `unsafe`, `extern`, identifier, `::`, `<`, `dyn`, square brackets, `*`, `&`, `!`, `impl`, `_`, lifetime
--> ui/local-malformed-1.rs:11:23
|
11 | #[task(local = [a:])]

View file

@ -2,4 +2,4 @@ error: malformed, expected 'IDENT: TYPE = EXPR'
--> ui/local-malformed-2.rs:11:21
|
11 | #[task(local = [a: u32])]
| ^^^^^^
| ^

View file

@ -1,4 +1,4 @@
error: unexpected end of input, expected expression
error: unexpected end of input, expected an expression
--> ui/local-malformed-3.rs:11:29
|
11 | #[task(local = [a: u32 =])]

View file

@ -1,6 +1,5 @@
error: attributes are not supported here
--> ui/local-shared-attribute.rs:17:9
--> ui/local-shared-attribute.rs:18:9
|
17 | / #[test]
18 | | b, // Error
| |_________^
18 | b, // Error
| ^