From b6491e626a9342998bd16a9a3d7eafd1b9c78211 Mon Sep 17 00:00:00 2001 From: Alexander Polyakov Date: Sat, 1 Aug 2026 21:11:47 +0300 Subject: [PATCH] fix erroneous type inference for static class fields of array type A static field's init value is stored in php globals and is reset via hard_reset_var() on every request startup, where memory allocations are forbidden; its constant initializer must therefore have exactly the same C++ type as the field itself (otherwise a converting copy_from() is generated, which allocates memory and crashes) --- compiler/pipes/optimization.cpp | 5 ++++ .../phpt/cl/200_static_field_array_infer.php | 29 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 tests/phpt/cl/200_static_field_array_infer.php diff --git a/compiler/pipes/optimization.cpp b/compiler/pipes/optimization.cpp index 33a28eaaad..1ce099e507 100644 --- a/compiler/pipes/optimization.cpp +++ b/compiler/pipes/optimization.cpp @@ -448,6 +448,11 @@ void OptimizationPass::on_finish() { class_id->members.for_each([this](ClassMemberStaticField &static_field) { if (static_field.var->init_val) { run_function_pass(static_field.var->init_val, this); + // a static field's init value is stored in php globals and is reset via hard_reset_var() + // on every request startup, where memory allocations are forbidden; + // its constant initializer must therefore have exactly the same C++ type as the field itself + // (otherwise a converting copy_from() is generated, which allocates memory and crashes) + explicit_cast_array_type(static_field.var->init_val, tinf::get_type(static_field.var)); } }); } diff --git a/tests/phpt/cl/200_static_field_array_infer.php b/tests/phpt/cl/200_static_field_array_infer.php new file mode 100644 index 0000000000..a97a89e7de --- /dev/null +++ b/tests/phpt/cl/200_static_field_array_infer.php @@ -0,0 +1,29 @@ +@ok +. Previously, it could be inferred as + * array. + * + * With array, a conversion to array would be required, which + * is not allowed in static variable initialization: the init value must + * have exactly the same C++ type as the field itself. + */ + +class SearchFilter { + public const REASON_A = 'reason_a'; + public const REASON_B = 'reason_b'; + public const REASON_C = 'reason_c'; + public const REASON_D = 'reason_d'; + + /** @var int[][] */ + private static $filtered_ids_by_reason = [ + self::REASON_A => [], + self::REASON_B => [], + self::REASON_C => [], + self::REASON_D => [], + ]; +} + +var_dump(new SearchFilter === new SearchFilter);