[PHP-DEV] [php-src] PR #20903: GH-10497 (const obj->prop write) - language change notes

Hi internals,

I opened PR #20903 to address GH-10497 by allowing writes to properties of objects referenced by consts (const binding stays immutable, referenced objects can be mutable).

class C { public int $x = 0; } const OBJ = new C(); OBJ->x = 1; // currently rejected, PR makes it valid var_dump(OBJ->x); // 1

Notes:

  • This is a language/semantics change and may overlap with / impact GH-13800.

  • A potentially surprising case: some newly-valid writes can be a no-op when they target a temporary const value, e.g.

  • const X = [1,2,3]; X = 4;

  • const Y = [‘a’ => 1]; Y[‘b’] = 2;

These become valid syntax but have no effect because the write happens on a temporary basis.

Feedback on semantics + expected behavior for the temporary-write case is appreciated.

Thanks,

···

__

Khaled Alam

Hi

On 1/15/26 07:36, Khaled Alam wrote:

    A potentially surprising case: some newly-valid writes can be a no-op
    when they target a temporary const value, e.g.
    - const X = [1,2,3]; X[] = 4;
       - const Y = ['a' => 1]; Y['b'] = 2;

These become valid syntax but have no effect because the write happens on a
temporary basis.

Feedback on semantics + expected behavior for the temporary-write case is
appreciated.

This is too unexpected / error-prone for me. Trying to write into arrays should remain disallowed / an Error, since this is never (?) useful.

For objects, I don't have a strong opinion, but I expect objects in constants to be so rare that it probably isn't worth it to make a change at all.

Best regards
Tim Düsterhus

Hi Tim

On Sun, Jan 18, 2026 at 1:28 PM Tim Düsterhus <tim@bastelstu.be> wrote:

On 1/15/26 07:36, Khaled Alam wrote:
> A potentially surprising case: some newly-valid writes can be a no-op
> when they target a temporary const value, e.g.
> - const X = [1,2,3]; X[] = 4;
> - const Y = ['a' => 1]; Y['b'] = 2;
>
> These become valid syntax but have no effect because the write happens on a
> temporary basis.
>
> Feedback on semantics + expected behavior for the temporary-write case is
> appreciated.

This is too unexpected / error-prone for me. Trying to write into arrays
should remain disallowed / an Error, since this is never (?) useful.

No strong opinions on my part, but I'd like to point out that similar
situations already exist.

    const C = [1, 2, 3];
    function foo(): array {
        return C;
    }
    foo()[] = 4;
    var_dump(C);

PHP will happily duplicate the array returned from foo() to append 4,
without warning. The original array in C remains unmodified. It might
make sense for ASSIGN_DIM to warn/throw if OP1 is not a "pointer"
(indirect, reference or object), as then the operation will never have
an effect. But it seems to me this is a distinct issue.

Ilija

Hi

Am 2026-01-22 00:33, schrieb Ilija Tovilo:

No strong opinions on my part, but I'd like to point out that similar
situations already exist.

Online PHP editor | output for ARMMS

    const C = [1, 2, 3];
    function foo(): array {
        return C;
    }
    foo()[] = 4;
    var_dump(C);

PHP will happily duplicate the array returned from foo() to append 4,
without warning. The original array in C remains unmodified. It might

I'm aware. However to me this situation is a little different, intuition-wise: A return value already looks and feels like a temporary value to me (unless a by-ref return is used, of course, but those are rare). An access on a const does not.

make sense for ASSIGN_DIM to warn/throw if OP1 is not a "pointer"
(indirect, reference or object), as then the operation will never have
an effect. But it seems to me this is a distinct issue.

That makes sense to me and IMO is a necessary precursor for this.

Best regards
Tim Düsterhus