From a8d9fc683e5cddb7ddd8295e99079c6a65269617 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 8 Jun 2026 14:06:32 -0400 Subject: [PATCH 1/2] Remove unmaintained proc-macro-error2 dependency (RUSTSEC-2026-0173) --- mlua_derive/Cargo.toml | 3 +-- mlua_derive/src/chunk/mod.rs | 8 +++--- mlua_derive/src/chunk/token.rs | 48 ++++++++++++++++------------------ mlua_derive/src/lib.rs | 8 +++--- 4 files changed, 33 insertions(+), 34 deletions(-) diff --git a/mlua_derive/Cargo.toml b/mlua_derive/Cargo.toml index c49d7d39..b7b4f20f 100644 --- a/mlua_derive/Cargo.toml +++ b/mlua_derive/Cargo.toml @@ -13,11 +13,10 @@ license = "MIT" proc-macro = true [features] -macros = ["proc-macro-error2", "itertools"] +macros = ["itertools"] [dependencies] quote = "1.0" proc-macro2 = { version = "1.0", features = ["span-locations"] } -proc-macro-error2 = { version = "2.0.1", optional = true } syn = { version = "2.0", features = ["full"] } itertools = { version = "0.14", optional = true } diff --git a/mlua_derive/src/chunk/mod.rs b/mlua_derive/src/chunk/mod.rs index 50306e89..df618f16 100644 --- a/mlua_derive/src/chunk/mod.rs +++ b/mlua_derive/src/chunk/mod.rs @@ -63,8 +63,8 @@ pub(crate) struct Chunk { } impl Chunk { - pub(crate) fn new(tokens: TokenStream) -> Self { - let tokens = Tokens::retokenize(tokens); + pub(crate) fn new(tokens: TokenStream) -> Result { + let tokens = Tokens::retokenize(tokens)?; let mut source = String::new(); let mut caps = Captures::new(); @@ -91,10 +91,10 @@ impl Chunk { prev_end = Some(t.end()); } - Self { + Ok(Self { source: source.trim_end().to_string(), caps, - } + }) } pub(crate) fn captures(&self) -> &[Capture] { diff --git a/mlua_derive/src/chunk/token.rs b/mlua_derive/src/chunk/token.rs index 51c565c3..a6ff9eec 100644 --- a/mlua_derive/src/chunk/token.rs +++ b/mlua_derive/src/chunk/token.rs @@ -2,9 +2,10 @@ use std::cmp::{Eq, PartialEq}; use std::fmt::{self, Display, Formatter}; use std::vec::IntoIter; -use itertools::Itertools; use proc_macro::{Delimiter, Span, TokenStream, TokenTree}; use proc_macro2::Span as Span2; +use proc_macro2::TokenStream as TokenStream2; +use syn; #[derive(Clone, Copy, Debug)] pub(crate) struct Pos { @@ -39,9 +40,7 @@ fn span_pos(span: &Span) -> (Pos, Pos) { // Rust 1.88 stabilized Span APIs, so this branch must be unreachable if start.line == 0 || end.line == 0 { - proc_macro_error2::abort_call_site!( - "cannot retrieve span location information; mlua requires nightly Rust or stable >= 1.88" - ); + unreachable!("cannot retrieve span location information; mlua requires nightly Rust or stable >= 1.88"); } (Pos::new(start.line, start.column), Pos::new(end.line, end.column)) @@ -133,27 +132,26 @@ impl Token { pub(crate) struct Tokens(pub(crate) Vec); impl Tokens { - pub(crate) fn retokenize(tt: TokenStream) -> Tokens { - Tokens( - tt.into_iter() - .flat_map(Tokens::from) - .batching(|iter| { - // Find variable tokens: `$` + `ident` => `$ident` - let t = iter.next()?; - if t.is("$") { - if let Some(next) = iter.next() - && matches!(next.tree, TokenTree::Ident(_)) - { - Some(next.attr(TokenAttr::Cap)) - } else { - proc_macro_error2::abort!(t.tree.span(), "`$` must be followed by an identifier"); - } - } else { - Some(t) - } - }) - .collect(), - ) + pub(crate) fn retokenize(tt: TokenStream) -> Result { + let flat: Vec = tt.into_iter().flat_map(Tokens::from).collect(); + let mut tokens = Vec::new(); + let mut iter = flat.into_iter(); + while let Some(t) = iter.next() { + // Find variable tokens: `$` + `ident` => `$ident` + if t.is("$") { + if let Some(next) = iter.next() + && matches!(next.tree, TokenTree::Ident(_)) + { + tokens.push(next.attr(TokenAttr::Cap)); + } else { + return Err(syn::Error::new(t.tree.span().into(), "`$` must be followed by an identifier") + .to_compile_error()); + } + } else { + tokens.push(t); + } + } + Ok(Tokens(tokens)) } } diff --git a/mlua_derive/src/lib.rs b/mlua_derive/src/lib.rs index 8fc6dd49..1031e13c 100644 --- a/mlua_derive/src/lib.rs +++ b/mlua_derive/src/lib.rs @@ -3,7 +3,7 @@ use proc_macro::TokenStream; mod module; #[cfg(feature = "macros")] -use {crate::chunk::Chunk, proc_macro_error2::proc_macro_error}; +use crate::chunk::Chunk; #[cfg(feature = "macros")] macro_rules! try_compile { @@ -22,9 +22,11 @@ pub fn lua_module(attr: TokenStream, item: TokenStream) -> TokenStream { #[cfg(feature = "macros")] #[proc_macro] -#[proc_macro_error] pub fn chunk(input: TokenStream) -> TokenStream { - Chunk::new(input).expand().into() + match Chunk::new(input) { + Ok(chunk) => chunk.expand().into(), + Err(err) => err.into(), + } } #[cfg(feature = "macros")] From 726dc186dc8fd242ddbf32d1d9ed40e69e6e04ca Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 8 Jun 2026 14:13:06 -0400 Subject: [PATCH 2/2] Use syn::Error compile error instead of unreachable! for span_pos failure --- mlua_derive/src/chunk/token.rs | 65 ++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/mlua_derive/src/chunk/token.rs b/mlua_derive/src/chunk/token.rs index a6ff9eec..ab580414 100644 --- a/mlua_derive/src/chunk/token.rs +++ b/mlua_derive/src/chunk/token.rs @@ -1,10 +1,10 @@ use std::cmp::{Eq, PartialEq}; +use std::convert::TryFrom; use std::fmt::{self, Display, Formatter}; use std::vec::IntoIter; use proc_macro::{Delimiter, Span, TokenStream, TokenTree}; -use proc_macro2::Span as Span2; -use proc_macro2::TokenStream as TokenStream2; +use proc_macro2::{Span as Span2, TokenStream as TokenStream2}; use syn; #[derive(Clone, Copy, Debug)] @@ -33,17 +33,21 @@ impl Pos { } } -fn span_pos(span: &Span) -> (Pos, Pos) { +fn span_pos(span: &Span) -> Result<(Pos, Pos), TokenStream2> { let span2: Span2 = (*span).into(); let start = span2.start(); let end = span2.end(); // Rust 1.88 stabilized Span APIs, so this branch must be unreachable if start.line == 0 || end.line == 0 { - unreachable!("cannot retrieve span location information; mlua requires nightly Rust or stable >= 1.88"); + return Err(syn::Error::new( + Span2::call_site(), + "cannot retrieve span location information; mlua requires nightly Rust or stable >= 1.88", + ) + .to_compile_error()); } - (Pos::new(start.line, start.column), Pos::new(end.line, end.column)) + Ok((Pos::new(start.line, start.column), Pos::new(end.line, end.column))) } /// Attribute of token. @@ -73,33 +77,32 @@ impl PartialEq for Token { impl Eq for Token {} impl Token { - fn new(tree: TokenTree) -> Self { - let (start, end) = span_pos(&tree.span()); + fn new(tree: TokenTree) -> Result { + let (start, end) = span_pos(&tree.span())?; let source = tree.span().source_text().unwrap_or_else(|| tree.to_string()); - Self { + Ok(Self { source, start, end, tree, attr: TokenAttr::None, - } + }) } - fn new_delim(source: String, tree: TokenTree, open: bool) -> Self { - let (start, end) = span_pos(&tree.span()); + fn new_delim(source: String, tree: TokenTree, open: bool) -> Result { + let (start, end) = span_pos(&tree.span())?; let (start, end) = if open { (start, start.right()) } else { (end.left(), end) }; - - Self { + Ok(Self { source, tree, start, end, attr: TokenAttr::None, - } + }) } pub(crate) fn tree(&self) -> &TokenTree { @@ -133,7 +136,11 @@ pub(crate) struct Tokens(pub(crate) Vec); impl Tokens { pub(crate) fn retokenize(tt: TokenStream) -> Result { - let flat: Vec = tt.into_iter().flat_map(Tokens::from).collect(); + let mut flat = Vec::new(); + for tree in tt.into_iter() { + flat.extend(Tokens::try_from(tree)?.0); + } + let mut tokens = Vec::new(); let mut iter = flat.into_iter(); while let Some(t) = iter.next() { @@ -144,8 +151,11 @@ impl Tokens { { tokens.push(next.attr(TokenAttr::Cap)); } else { - return Err(syn::Error::new(t.tree.span().into(), "`$` must be followed by an identifier") - .to_compile_error()); + return Err(syn::Error::new( + t.tree.span().into(), + "`$` must be followed by an identifier", + ) + .to_compile_error()); } } else { tokens.push(t); @@ -164,8 +174,10 @@ impl IntoIterator for Tokens { } } -impl From for Tokens { - fn from(tt: TokenTree) -> Self { +impl TryFrom for Tokens { + type Error = TokenStream2; + + fn try_from(tt: TokenTree) -> Result { let tts = match tt.clone() { TokenTree::Group(g) => { let (b, e) = match g.delimiter() { @@ -176,15 +188,16 @@ impl From for Tokens { }; let (b, e) = (b.into(), e.into()); - vec![Token::new_delim(b, tt.clone(), true)] - .into_iter() - .chain(g.stream().into_iter().flat_map(Tokens::from)) - .chain(vec![Token::new_delim(e, tt, false)]) - .collect() + let mut result = vec![Token::new_delim(b, tt.clone(), true)?]; + for inner in g.stream().into_iter() { + result.extend(Tokens::try_from(inner)?.0); + } + result.push(Token::new_delim(e, tt, false)?); + result } - _ => vec![Token::new(tt)], + _ => vec![Token::new(tt)?], }; - Tokens(tts) + Ok(Tokens(tts)) } }