From a7c145fb1b3ff44ed5318b4997228301c9c6b783 Mon Sep 17 00:00:00 2001 From: Jakob Jungreuthmayer <116195279+jakobjung10@users.noreply.github.com> Date: Sun, 12 Jul 2026 01:12:36 +0200 Subject: [PATCH] fix(emit): wrap no_mangle-family attrs as unsafe for edition-2024 round-trip When the generated crate is pretty-printed and recompiled at the 2024 edition, bare `#[no_mangle]` / `#[export_name]` / `#[link_section]` attributes are rejected. Macros expanded from earlier-edition dependencies can emit the bare form, which broke recompilation of the mutant crate. In the macro-expansion sanitizer, rewrite these attributes to the `#[unsafe(...)]` form when the session edition is 2024 or later. --- mutest-emit/src/codegen/hygiene.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/mutest-emit/src/codegen/hygiene.rs b/mutest-emit/src/codegen/hygiene.rs index d3efe787..cf6bcb3e 100644 --- a/mutest-emit/src/codegen/hygiene.rs +++ b/mutest-emit/src/codegen/hygiene.rs @@ -1514,7 +1514,19 @@ impl<'tcx, 'op> ast::mut_visit::MutVisitor for MacroExpansionSanitizer<'tcx, 'op if is_macro_helper_attr(&self.syntax_extensions, attr) { // Disable attribute by overriding it with an empty doc-comment. // This is easier than modifying every visit function to properly remove the attribute nodes. - attr.kind = ast::AttrKind::DocComment(ast::token::CommentKind::Line, sym::empty) + attr.kind = ast::AttrKind::DocComment(ast::token::CommentKind::Line, sym::empty); + return; + } + + // In Rust 2024 `no_mangle`/`export_name`/`link_section` must be written as `unsafe(...)`. + // Macros from earlier-edition crates can emit the bare form, which is invalid once the + // generated crate is recompiled at the 2024 edition; wrap it to keep the round-trip valid. + if self.tcx.sess.edition().at_least_rust_2024() + && (attr.has_name(sym::no_mangle) || attr.has_name(sym::export_name) || attr.has_name(sym::link_section)) + && let ast::AttrKind::Normal(normal) = &mut attr.kind + && let ast::Safety::Default = normal.item.unsafety + { + normal.item.unsafety = ast::Safety::Unsafe(DUMMY_SP); } }