Skip to content

Captureless closures can still codegen to fn call(&self) / fn call_mut(&mut self). #53704

Open
@eddyb

Description

@eddyb

Despite them being ZSTs and Copy, which would allow Fn / FnMut impls on top of FnOnce.

This small example:

fn foo(f: impl FnOnce()) { f() }
pub fn test() {
    // Not passed directly in call to avoid inferring `closure` to `FnOnce`.
    let closure = || {};
    foo(closure);
}

will cause a ClosureOnceShim to be generated, which takes the ZST closure, borrows it, and passes it to the actual closure "function", that has been inferred to be Fn (I think?).

While correct, it's an extra function between the caller and the closure, and there's a potential risk of LLVM doing not-that-nice (e.g. inlining-related) things (and mergefunc might not work here).

This seems tricky to fix, since parts of the compiler assume that e.g. a closure implements FnMut if it can be called with a mutable reference to its environment, and if it implements FnMut and not Fn, then its "codegen'd function" must have a FnMut::call_mut signature.

cc @rust-lang/wg-codegen

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-codegenArea: Code generationC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.WG-llvmWorking group: LLVM backend code generation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions