rust-lang / rust-lang/reference

Inline assembly lifetime extension / statement

Open
#1,976 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-asm
Dominant language
Rust
Stars
1.6k
Forks
607
PR merge metrics
PR metrics pending

Description

This began as this URLO thread: https://users.rust-lang.org/t/end-of-statement-lifetime-in-inline-assembly-blocks/133373

I have have code like:

    pub fn macro_generated_function(location: &std::panic::Location) {
        unsafe {
            std::arch::asm!(
                "... {0} ...",
                in (reg) (std::ffi::CString::new(location.file()).unwrap().as_ptr()) as isize,
                options(readonly, preserves_flags, nostack, att_syntax)
            )
        };
    }

This results in a warning:

warning: a dangling pointer will be produced because the temporary `CString` will be dropped
   --> src/lib.rs:498:76
    |
498 |                 in (reg) (std::ffi::CString::new(location.file()).unwrap().as_ptr()) as isize,
    |                           ------------------------------------------------ ^^^^^^ this pointer will immediately be invalid
    |                           |
    |                           this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
    |
    = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
    = help: you must make sure that the variable you bind the `CString` to lives at least as long as the pointer returned by the call to `as_ptr`
    = help: in particular, if this pointer is returned from the current function, binding the `CString` inside the function will not suffice
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
    = note: `#[warn(dangling_pointers_from_temporaries)]` on by default

However, it isn't clear from the reference what the "statement" is when it comes to a macro like asm!. Is the statement the whole asm!() (in which case it is fine for my use case), or does the lifetime end before the assembly code is executed? Wouldn't lifetime extension extend this lifetime to the end of the asm!()?

"Normal" macros can after all expand to multiple statements, and it is unclear what the semantics are around a built in macro like asm!. The code does work in practise (the destructor appears to be called after the inline assembly, see godbolt) but I would like this to be properly documented (presumably at https://doc.rust-lang.org/reference/inline-assembly.html)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the inline-assembly section of the Rust Reference, then review the linked URLO discussion and Godbolt example. Determine how statement boundaries and temporary lifetime extension apply to asm! operands and identify the precise behavior that needs documenting. Done means the Reference clearly explains when the temporary is dropped relative to the assembly execution.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
documentation
Issue type
Documentation
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.