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);