-
Notifications
You must be signed in to change notification settings - Fork 13.6k
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
ret
Metadata
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