Open
Description
The following example (playground):
#![feature(generators, generator_trait)]
use std::ops::Generator;
#[derive(Clone)]
struct Foo([u8; 1024]);
fn overlap_foo() -> impl Generator<Yield = (), Return = ()>{
static || {
let x = Foo([0u8; 1024]);
yield;
drop(x);
let y = Foo([0u8; 1024]);
yield;
drop(y);
}
}
#[derive(Clone, Copy)]
struct Bar([u8; 1024]);
fn overlap_bar() -> impl Generator<Yield = (), Return = ()>{
static || {
let x = Bar([0u8; 1024]);
yield;
drop(x);
let y = Bar([0u8; 1024]);
yield;
drop(y);
}
}
fn main() {
dbg!(std::mem::size_of_val(&overlap_foo()));
dbg!(std::mem::size_of_val(&overlap_bar()));
}
Outputs:
[gen-explicit-drop.rs:34] std::mem::size_of_val(&overlap_foo()) = 1028
[gen-explicit-drop.rs:35] std::mem::size_of_val(&overlap_bar()) = 2052
The only difference between Foo and Bar is that Foo is Copy. This defeats the generator optimization implemented in #61922 which considers any local that has been moved from as a candidate for overlap.
Technically, this is semantically consistent with the existing overlap behavior for generators. But making a type Copy
and getting worse performance is a footgun that we should fix.
This can be fixed with a pass that turns unnecessary copies into moves in MIR.
Metadata
Metadata
Assignees
Labels
Area: CoroutinesCategory: An issue proposing an enhancement or a PR with one.Category: An issue highlighting optimization opportunities or PRs implementing suchIssue: Problems and improvements with respect to binary size of generated code.Relevant to the compiler team, which will review and decide on the PR/issue.