- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Open
Labels
A-closuresArea: Closures (`|…| { … }`)Area: Closures (`|…| { … }`)A-edition-2021Area: The 2021 editionArea: The 2021 editionC-bugCategory: This is a bug.Category: This is a bug.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.P-mediumMedium priorityMedium priority
Description
In Rust 2021 the borrow checker got extended to see through borrow paths when writing closures. I've been wondering how this is implemented, but it seems like it's basically just syntax sugar for individual manual borrows that get moved in. This however leads to worse codegen than when a move closure would've been possible. So you might end up with code that performs worse by accident:
pub struct Foo {
    x: f32,
    y: f32,
    z: f32,
}
pub fn with_move(bar: &mut Foo) -> impl Fn() -> f32 + '_ {
    move || bar.x + bar.y + bar.z
}
pub fn without_move(bar: &mut Foo) -> impl Fn() -> f32 + '_ {
    || bar.x + bar.y + bar.z
}example::with_move:
        mov     rax, rdi
        ret
example::without_move:
        mov     rax, rdi
        lea     rcx, [rsi + 4]
        mov     qword ptr [rdi], rsi
        add     rsi, 8
        mov     qword ptr [rdi + 8], rcx
        mov     qword ptr [rdi + 16], rsi
        retMetadata
Metadata
Assignees
Labels
A-closuresArea: Closures (`|…| { … }`)Area: Closures (`|…| { … }`)A-edition-2021Area: The 2021 editionArea: The 2021 editionC-bugCategory: This is a bug.Category: This is a bug.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.P-mediumMedium priorityMedium priority