Skip to content

Allow global_asm! in statement positions#156582

Open
daxpedda wants to merge 2 commits into
rust-lang:mainfrom
daxpedda:global-asm-statement
Open

Allow global_asm! in statement positions#156582
daxpedda wants to merge 2 commits into
rust-lang:mainfrom
daxpedda:global-asm-statement

Conversation

@daxpedda
Copy link
Copy Markdown
Contributor

@daxpedda daxpedda commented May 14, 2026

This PR makes it possible to put global_asm! in statement positions. This is particularly useful for proc-macros, where you otherwise have to wrap them in mod foo { global_asm!(...); }.

I'm happy to open an ACP first (or a design meeting?).
I would also assume this needs sign-off from the lang-team?

Previously discussed on Zulip.

r? @Amanieu

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 14, 2026
@rust-log-analyzer

This comment has been minimized.

@daxpedda daxpedda marked this pull request as draft May 14, 2026 18:47
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 14, 2026
@daxpedda daxpedda force-pushed the global-asm-statement branch from fc5f2bf to 76f8edb Compare May 14, 2026 21:34
Copy link
Copy Markdown
Contributor Author

@daxpedda daxpedda May 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main issue is that GlobalAsm is an Item. In expand_invoc(), it will try to extract the node depending on AstFragmentKind. Until now we only expected it on the item level. But now it can be either an item or a statement. If its a statement, it will find an item and return an error saying that non-statement macros are not allowed in statement positions. So somehow we have to make the macro an item and statement at the same time or change whats expected.

I spent quite some time trying to figure out how this could be done. AFAIU:

  • The macro is considered a AstFragmentKind::Stmts because its considered a ast::Stmt. Special casing this would require changing InvocationCollectorNode.
  • I could try to move away from SyntaxExtensionKind::BangLegacy:
    if let SyntaxExtensionKind::Bang(expander) = ext {
    match expander.expand(self.cx, span, mac.args.tokens.clone()) {
    Ok(tok_result) => {
    let fragment =
    self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span);
    if macro_stats {
    update_bang_macro_stats(
    self.cx,
    fragment_kind,
    span,
    mac,
    &fragment,
    );
    }
    fragment
    }
    Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
    }
    } else if let Some(expander) = ext.as_legacy_bang() {
    let tok_result = match expander.expand(self.cx, span, mac.args.tokens.clone()) {
    ExpandResult::Ready(tok_result) => tok_result,
    ExpandResult::Retry(_) => {
    // retry the original
    return ExpandResult::Retry(Invocation {
    kind: InvocationKind::Bang { mac, span },
    ..invoc
    });
    }
    };
    if let Some(fragment) = fragment_kind.make_from(tok_result) {
    if macro_stats {
    update_bang_macro_stats(self.cx, fragment_kind, span, mac, &fragment);
    }
    fragment
    } else {
    let guar = self.error_wrong_fragment_kind(fragment_kind, &mac, span);
    fragment_kind.dummy(span, guar)
    }
    } else {
    unreachable!();
    }

    But that does already implement a lot of special casing for (*_)asm!.
  • Changing it to something else then ast::Stmt is presumably a terrible idea.
  • Adapting MacEager would be possible, but not through the MacResult interface. The only information it has is what kind of AstFragmentKind we are dealing with. So some information has to be stored on MacEager. That turned out to be much more code.
  • Ideally expand_global_asm() could simply store the right MacEager type, but it doesn't know what AstFragmentKind will be asked of it.

So just introducing a new MacResult implementation felt like the best solution.
Maybe somebody more knowledgeable about the parser could pinpoint exactly where we could special case this more easily.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some more thinking I believe the best alternative is adapting MacEager. E.g. adding a upgradable_to_stmt: bool, in which case make_stmts would upgrade potentially existing items to ast::Stmts.

Let me know if that is the preferred change.

@daxpedda daxpedda force-pushed the global-asm-statement branch from 76f8edb to d0629e2 Compare May 14, 2026 22:14
@daxpedda daxpedda marked this pull request as ready for review May 14, 2026 22:15
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants