From 8b9236bf59a4f78ec9b481e32c4b896d722064e9 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Sat, 25 Jul 2026 16:44:06 +0000 Subject: [PATCH 20/25] expand: ignore trailing semicolon of tail-position macro expansions rustc accepts a macro expansion ending in `;` when the invocation is in expression position (the `semicolon_in_expressions_from_macros` backcompat rule). mrustc kept the semicolon, so a block whose tail was such a macro evaluated to `()` -> bogus "Type mismatch between and ()" with a null span. Now, when the invocation had no semicolon and was the last line of its block, the expansion's final line has its semicolon cleared (unless it is a let binding). Seen with syn 0.13.9, whose `parens!`/`named!` combinators expand through an arm that appends `;` in tail position (blocks xsv). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01GNXc7PddzJE4X1swqbe3Xn --- src/expand/mod.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index 17d91f2f..c4519f33 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -993,6 +993,16 @@ struct CExpandExpr: if( it->has_semicolon && !new_nodes.empty() ) { new_nodes.back().has_semicolon = true; } + // If this macro invocation had NO semicolon and was the tail node of the + // block, then it's in expression position - any trailing semicolon that the + // expansion introduced on its own last line must be dropped (rustc's + // `semicolon_in_expressions_from_macros` backcompat behaviour), so the block + // still evaluates to the expansion's value rather than `()`. + else if( !it->has_semicolon && (it + 1) == node.m_nodes.end() && !new_nodes.empty() ) { + if( !dynamic_cast<::AST::ExprNode_LetBinding*>(new_nodes.back().node.get()) ) { + new_nodes.back().has_semicolon = false; + } + } it = node.m_nodes.erase(it); it = node.m_nodes.insert(it, ::std::make_move_iterator(new_nodes.begin()), ::std::make_move_iterator(new_nodes.end())); // NOTE: Doesn't advance the iterator above, we want to re-visit the new node -- 2.43.0