diff --git a/runtime-common/core/core-types/kphp_type_traits.h b/runtime-common/core/core-types/kphp_type_traits.h index 2ba06b531c..d984f530d1 100644 --- a/runtime-common/core/core-types/kphp_type_traits.h +++ b/runtime-common/core/core-types/kphp_type_traits.h @@ -3,8 +3,11 @@ // Distributed under the GPL v3 License, see LICENSE.notice.txt #pragma once + +#include #include #include +#include #include "common/type_traits/list_of_types.h" @@ -36,6 +39,18 @@ struct is_class_instance : std::false_type {}; template struct is_class_instance> : std::true_type {}; +template +struct is_tuple : std::false_type {}; + +template +struct is_tuple> : std::true_type {}; + +template +struct is_shape : std::false_type {}; + +template +struct is_shape, Ts...>> : std::true_type {}; + template inline constexpr bool is_class_instance_v = is_class_instance::value; diff --git a/runtime-light/core/reference-counter/reference-counter-functions.h b/runtime-light/core/reference-counter/reference-counter-functions.h index 56b73b86d7..fa0fa2c6d5 100644 --- a/runtime-light/core/reference-counter/reference-counter-functions.h +++ b/runtime-light/core/reference-counter/reference-counter-functions.h @@ -4,52 +4,35 @@ #pragma once +#include +#include #include #include "common/php-functions.h" #include "runtime-common/core/core-types/kphp_type_traits.h" #include "runtime-common/core/runtime-core.h" +#include "runtime-light/stdlib/diagnostics/logs.h" namespace kphp::core { -template -void set_reference_counter_recursive(Optional& obj, ExtraRefCnt rc) noexcept; - template void set_reference_counter_recursive(class_instance& obj, ExtraRefCnt rc) noexcept; template void set_reference_counter_recursive(array& obj, ExtraRefCnt rc) noexcept; -template -requires(!is_array::value && !is_class_instance::value && !is_optional::value) -void set_reference_counter_recursive(T& /*obj*/, ExtraRefCnt /*rc*/) noexcept {} +template +void set_reference_counter_recursive(std::tuple& obj, ExtraRefCnt rc) noexcept; -template -void set_reference_counter_recursive(Optional& obj, ExtraRefCnt rc) noexcept { - if (obj.has_value()) { - set_reference_counter_recursive(obj.val(), rc); - } -} +template +void set_reference_counter_recursive(shape, Ts...>& obj, ExtraRefCnt rc) noexcept; template -void set_reference_counter_recursive(class_instance& obj, ExtraRefCnt rc) noexcept { - if (!obj.is_null()) { - // TODO we need some visitor to visit all the class member - obj.set_reference_counter_to(rc); - } -} +void set_reference_counter_recursive(Optional& obj, ExtraRefCnt rc) noexcept; template -void set_reference_counter_recursive(array& obj, ExtraRefCnt rc) noexcept { - obj.set_reference_counter_to(rc); - for (const auto& it : std::as_const(obj)) { - auto key{it.get_key()}; - set_reference_counter_recursive(key, rc); - auto value{it.get_value()}; - set_reference_counter_recursive(value, rc); - } -} +requires(!is_class_instance::value && !is_array::value && !is_tuple::value && !is_shape::value && !is_optional::value) +void set_reference_counter_recursive(T& /*obj*/, ExtraRefCnt /*rc*/) noexcept {} template<> inline void set_reference_counter_recursive(string& obj, ExtraRefCnt rc) noexcept { @@ -65,52 +48,69 @@ inline void set_reference_counter_recursive(mixed& obj, ExtraRefCnt rc) n case mixed::type::FLOAT: return; case mixed::type::STRING: + return set_reference_counter_recursive(obj.as_string(), rc); case mixed::type::OBJECT: - return obj.set_reference_counter_to(rc); + kphp::log::assertion(false); case mixed::type::ARRAY: return set_reference_counter_recursive(obj.as_array(), rc); } } -// ================================================================================================ - template -bool is_reference_counter_recursive(const Optional& obj, ExtraRefCnt rc) noexcept; +void set_reference_counter_recursive(class_instance& obj, ExtraRefCnt /*rc*/) noexcept { + if (!obj.is_null()) { + kphp::log::assertion(false); + } +} template -bool is_reference_counter_recursive(const class_instance& obj, ExtraRefCnt rc) noexcept; +void set_reference_counter_recursive(array& obj, ExtraRefCnt rc) noexcept { + obj.set_reference_counter_to(rc); + for (const auto& it : std::as_const(obj)) { + auto key{it.get_key()}; + set_reference_counter_recursive(key, rc); + auto value{it.get_value()}; + set_reference_counter_recursive(value, rc); + } +} -template -bool is_reference_counter_recursive(const array& obj, ExtraRefCnt rc) noexcept; +template +void set_reference_counter_recursive(std::tuple& obj, ExtraRefCnt rc) noexcept { + std::apply([&rc](auto&... e) noexcept { (set_reference_counter_recursive(e, rc), ...); }, obj); +} -template -requires(!is_array::value && !is_class_instance::value && !is_optional::value) -bool is_reference_counter_recursive(const T& /*obj*/, ExtraRefCnt /*rc*/) noexcept { - return true; +template +void set_reference_counter_recursive(shape, Ts...>& obj, ExtraRefCnt rc) noexcept { + (set_reference_counter_recursive(obj.template get(), rc), ...); } template -bool is_reference_counter_recursive(const Optional& obj, ExtraRefCnt rc) noexcept { - return obj.has_value() ? is_reference_counter_recursive(obj.val(), rc) : true; +void set_reference_counter_recursive(Optional& obj, ExtraRefCnt rc) noexcept { + if (obj.has_value()) { + set_reference_counter_recursive(obj.val(), rc); + } } +// ================================================================================================ + template -bool is_reference_counter_recursive(const class_instance& obj, ExtraRefCnt rc) noexcept { - // TODO we need some visitor to visit all the class members - return !obj.is_null() ? obj.is_reference_counter(rc) : true; -} +bool is_reference_counter_recursive(const class_instance& obj, ExtraRefCnt rc) noexcept; template -bool is_reference_counter_recursive(const array& obj, ExtraRefCnt rc) noexcept { - if (!obj.is_reference_counter(rc)) { - return false; - } +bool is_reference_counter_recursive(const array& obj, ExtraRefCnt rc) noexcept; - for (const auto& it : obj) { // NOLINT - if (!is_reference_counter_recursive(it.get_key(), rc) || !is_reference_counter_recursive(it.get_value(), rc)) { - return false; - } - } +template +bool is_reference_counter_recursive(const std::tuple& obj, ExtraRefCnt rc) noexcept; + +template +bool is_reference_counter_recursive(const shape, Ts...>& obj, ExtraRefCnt rc) noexcept; + +template +bool is_reference_counter_recursive(const Optional& obj, ExtraRefCnt rc) noexcept; + +template +requires(!is_class_instance::value && !is_array::value && !is_tuple::value && !is_shape::value && !is_optional::value) +bool is_reference_counter_recursive(const T& /*obj*/, ExtraRefCnt /*rc*/) noexcept { return true; } @@ -128,11 +128,44 @@ inline bool is_reference_counter_recursive(const mixed& obj, ExtraRefCnt case mixed::type::FLOAT: return true; case mixed::type::STRING: + return is_reference_counter_recursive(obj.as_string(), rc); case mixed::type::OBJECT: - return obj.is_reference_counter(rc); + kphp::log::assertion(false); case mixed::type::ARRAY: return is_reference_counter_recursive(obj.as_array(), rc); } } +template +bool is_reference_counter_recursive(const class_instance& obj, ExtraRefCnt /*rc*/) noexcept { + if (!obj.is_null()) { + kphp::log::assertion(false); + } + return true; +} + +template +bool is_reference_counter_recursive(const array& obj, ExtraRefCnt rc) noexcept { + bool ok{obj.is_reference_counter(rc)}; + for (const auto& it : obj) { // NOLINT + ok = ok && is_reference_counter_recursive(it.get_key(), rc) && is_reference_counter_recursive(it.get_value(), rc); + } + return ok; +} + +template +bool is_reference_counter_recursive(const std::tuple& obj, ExtraRefCnt rc) noexcept { + return std::apply([&rc](auto&... e) noexcept { return (is_reference_counter_recursive(e, rc) && ...); }, obj); +} + +template +bool is_reference_counter_recursive(const shape, Ts...>& obj, ExtraRefCnt rc) noexcept { + return (is_reference_counter_recursive(obj.template get(), rc) && ...); +} + +template +bool is_reference_counter_recursive(const Optional& obj, ExtraRefCnt rc) noexcept { + return obj.has_value() ? is_reference_counter_recursive(obj.val(), rc) : true; +} + } // namespace kphp::core