From 218caa410aa38c29984be31a5229b9fa717560ee Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:13 +0200 Subject: Merging upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- tests/ui/generator/size-moved-locals.rs | 78 +++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 tests/ui/generator/size-moved-locals.rs (limited to 'tests/ui/generator/size-moved-locals.rs') diff --git a/tests/ui/generator/size-moved-locals.rs b/tests/ui/generator/size-moved-locals.rs new file mode 100644 index 000000000..601a31418 --- /dev/null +++ b/tests/ui/generator/size-moved-locals.rs @@ -0,0 +1,78 @@ +// run-pass +// Test that we don't duplicate storage for a variable that is moved to another +// binding. This used to happen in the presence of unwind and drop edges (see +// `complex` below.) +// +// The exact sizes here can change (we'd like to know when they do). What we +// don't want to see is the `complex` generator size being upwards of 2048 bytes +// (which would indicate it is reserving space for two copies of Foo.) +// +// See issue #59123 for a full explanation. + +// edition:2018 +// ignore-wasm32 issue #62807 +// ignore-asmjs issue #62807 +// needs-unwind Size of Closures change on panic=abort + +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +const FOO_SIZE: usize = 1024; +struct Foo(#[allow(unused_tuple_struct_fields)] [u8; FOO_SIZE]); + +impl Drop for Foo { + fn drop(&mut self) {} +} + +fn move_before_yield() -> impl Generator { + static || { + let first = Foo([0; FOO_SIZE]); + let _second = first; + yield; + // _second dropped here + } +} + +fn noop() {} + +fn move_before_yield_with_noop() -> impl Generator { + static || { + let first = Foo([0; FOO_SIZE]); + noop(); + let _second = first; + yield; + // _second dropped here + } +} + +// Today we don't have NRVO (we allocate space for both `first` and `second`,) +// but we can overlap `first` with `_third`. +fn overlap_move_points() -> impl Generator { + static || { + let first = Foo([0; FOO_SIZE]); + yield; + let second = first; + yield; + let _third = second; + yield; + } +} + +fn overlap_x_and_y() -> impl Generator { + static || { + let x = Foo([0; FOO_SIZE]); + yield; + drop(x); + let y = Foo([0; FOO_SIZE]); + yield; + drop(y); + } +} + +fn main() { + assert_eq!(1025, std::mem::size_of_val(&move_before_yield())); + assert_eq!(1026, std::mem::size_of_val(&move_before_yield_with_noop())); + assert_eq!(2051, std::mem::size_of_val(&overlap_move_points())); + assert_eq!(1026, std::mem::size_of_val(&overlap_x_and_y())); +} -- cgit v1.2.3