diff --git a/AK/Function.h b/AK/Function.h index fb887493ea..a4662867e4 100644 --- a/AK/Function.h +++ b/AK/Function.h @@ -357,6 +357,7 @@ private: case FunctionKind::Inline: case FunctionKind::Block: other_wrapper->init_and_swap(m_storage, inline_capacity); + other_wrapper->~CallableWrapperBase(); m_kind = other.m_kind; break; case FunctionKind::Outline: diff --git a/Tests/AK/CMakeLists.txt b/Tests/AK/CMakeLists.txt index 731fc236c7..4f17e9bb8c 100644 --- a/Tests/AK/CMakeLists.txt +++ b/Tests/AK/CMakeLists.txt @@ -27,6 +27,7 @@ set(AK_TEST_SOURCES TestFind.cpp TestFixedArray.cpp TestFixedPoint.cpp + TestFunction.cpp TestFlyString.cpp TestFormat.cpp TestGenericLexer.cpp diff --git a/Tests/AK/TestFunction.cpp b/Tests/AK/TestFunction.cpp new file mode 100644 index 0000000000..f465e65cf5 --- /dev/null +++ b/Tests/AK/TestFunction.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2026, Gregory Bertilson + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +#include +#include +#include + +namespace { + +struct CopyOnly { + int& instance_count; + + CopyOnly(int& count) + : instance_count(count) + { + instance_count++; + } + + CopyOnly(CopyOnly const& other) + : instance_count(other.instance_count) + { + instance_count++; + } + + ~CopyOnly() + { + instance_count--; + } +}; + +} + +TEST_CASE(move_construction_destroys_old_inline_wrapper) +{ + int instance_count = 0; + + { + Function source = [captured = CopyOnly(instance_count)]() { + (void)captured; + }; + EXPECT_EQ(instance_count, 1); + + Function destination = move(source); + EXPECT_EQ(instance_count, 1); + + source = nullptr; + EXPECT_EQ(instance_count, 1); + } + + EXPECT_EQ(instance_count, 0); +} + +TEST_CASE(move_assignment_destroys_old_inline_wrapper) +{ + int instance_count = 0; + + { + Function source = [captured = CopyOnly(instance_count)]() { + (void)captured; + }; + EXPECT_EQ(instance_count, 1); + + Function destination; + destination = move(source); + EXPECT_EQ(instance_count, 1); + + source = nullptr; + EXPECT_EQ(instance_count, 1); + } + + EXPECT_EQ(instance_count, 0); +}