rustriscv

How to fix "unsafe attribute used without unsafe" in custom attribute macro?


project: https://github.com/xiaguangbo/picorv32_and_rust

error code:

program_picorv32ec/project/src/main.rs

#[picorv32asm::entry]
fn main() -> ! {
    loop {}
}

error message:

$ cargo build
   Compiling picorv32asm v0.1.0 (/home/xiaguangbo/linux/project/custom_rv32_rust/program_picorv32ec/picorv32asm)
   Compiling project v0.1.0 (/home/xiaguangbo/linux/project/custom_rv32_rust/program_picorv32ec/project)
   Compiling picorv32entrymacro v0.1.0 (/home/xiaguangbo/linux/project/custom_rv32_rust/program_picorv32ec/picorv32asm/picorv32entrymacro)
error: unsafe attribute used without unsafe
--> src/main.rs:6:1
  |
6 | #[picorv32asm::entry]
  | ^^^^^^^^^^^^^^^^^^^^^ usage of unsafe attribute
  |
  = note: this error originates in the attribute macro `picorv32asm::entry` (in Nightly builds, run with -Z macro-backtrace for more info)
help: wrap the attribute in `unsafe(...)`
  |
6 | unsafe(#[picorv32asm::entry])
  | +++++++                     +

error: could not compile `project` (bin "project") due to 1 previous error

It doesn't work either if you follow the compiler's prompts.

I think other projects can also be written like this, such as wch rust project.


Solution

  • Your #[picorv32asm::entry] macro generates from this:

    quote!(
        #[export_name = "main"]
        fn main() -> ! {
            #(#stmts)*
        }
    )
    

    In the Rust 2024 edition, certain attributes were marked unsafe and you must wrap them in unsafe(...) to use them. #[export_name = ...] was one of those due to the possibility of global name conflicts. And since macros expand within the local crate, the error tries to suggest a fix there which won't work since you can't modify the macro output (directly).

    One solution as you show is to use an earlier edition in the local crate. Deleting edition = ... altogether will mean it defaults to 2015 but you'd likely be better served by 2018 or 2021.

    The other option is to update your macro to produce the new syntax.

    #[unsafe(export_name = "main")]