Skip to content

Symbol-mangling (v0) should show difference between async / closure / generator #104830

Open

Description

@Swatinem

The following code:

pub async fn fn_with_nested_block() -> Backtrace {
    None.unwrap_or_else(|| async { Backtrace::force_capture() })
        .await
}

Generates the following demangled symbol with legacy demangling:

async_codegen::fn_with_nested_block::{{closure}}::{{closure}}::{{closure}}

(v0 mangling is similar, but with {closure#0} instead)

Whereas Windows mangling gives this fn name:

async_codegen::fn_with_nested_block::async_fn$0::closure$0::async_block$0

This makes it clear what is an async fn, closure or async block. v0 symbol mangling should make a similar distinction.

#104333 is a first attempt to thread the necessary information through to the place that does the symbol mangling, but actually extending the v0 symbol mangling format / spec is necessary as well to fully solve this.

Activity

  1. jyn514 commented on Apr 12, 2023

    @jyn514
    Member

    v0 is a public spec that is already been implemented by other tools (e.g. gdb). is this proposed change backwards compatible? If not, is it enough to extend the tools or does there need to be a new v1 format?

  2. added
    A-linkageArea: linking into static, shared libraries and binaries
    A-closuresArea: Closures (`|…| { … }`)
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Apr 12, 2023
  3. sharnoff commented on Jun 15, 2025

    @sharnoff
    Contributor

    I hit this issue recently — I was digging into compile times for a project and having {closure#0} in the v0 mangling of an async function led me to incorrectly believe that the compiler was spending a long time optimizing a small closure in the function, rather than the main body of the async function.

    Reading through this issue and the v0 mangling format (link for reference), there's two options that come to mind:

    1. Embed generator information in an identifier attached to a shim/closure namespace — demangling might look like my_crate::my_fn::{shim:async_fn}::{closure#0}::{closure:async_block#0}
    2. Add new namespace tags, alongside "closure" and "shim". Demangling could look like my_crate::my_fn::{async_fn}::{closure#0}::{async_block#0}.
      • Perhaps we'd want to keep async fn as a "shim" but async { ... } as a unique namespace type. There's a few potential routes here

    The v0 spec does say to account for new tags being added, but it seems like the second route would still require a new version.


    Maybe a reasonable path forward would be to use option (1) with the v0 format, but also start work on a v1 that allows option (2) ?

    I'm not sure what the long-term path should be w.r.t. representing new language features in symbols — it'd be unfortunate if a wide swathe of tools need to be updated before each language feature, but including the block types as full identifiers in the symbol (e.g. async_block?) is also a lot of extra characters.

    Either way, I'm happy to try picking up #104333 following option (1), if that'd be worthwhile?

  4. kornelski commented on Jun 27, 2025

    @kornelski
    Contributor

    The v0 spec already has names for closures, they're just set to an empty string by rustc.

    _RNCNvCsgStHSCytQ6I_7mycrate4main0B3_
                                     ^ 0 is the length of the closure's name
    mycrate::main::{closure#0}
    
    _RNCNvCsgStHSCytQ6I_7mycrate4main5asyncB3_
                                     ^ 5async makes it a 5-byte "async" string
    mycrate::main::{closure:async#0}
    

    I've checked that the C port supports this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)A-linkageArea: linking into static, shared libraries and binariesT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions