Hi Alexandru, hi Shinji

> Hey, sorry to bump here on this topic.
>
> My assumption was that the use of `->` in initializers would bear the same 
> limitations as using `new`.
> That would mean it would not be supported for
> - class constant initializers
> - instance property initializers
> - static property initializers
>
> For `new` clarifications are here: 
> https://wiki.php.net/rfc/new_in_initializers#unsupported_positions
>
> My assumption is that `->` would only work for:
> - static variable initializers
> - global constant initializers
> - parameter default values
> - attribute arguments
>
> The examples shared by Shinji are for class constant initializers in class C 
> and I'm guessing it would not work.
> If that's the case, I think we should clarify this in the RFC as well.

Thank you for bringing this to my attention. I have missed the case
where, through constants, side-effects could be triggered in contexts
where they shouldn't.

class A {
    public function __get($name) {}
}
const A = new A();

class B {
    public $c = A->c;
}

I was under the incorrect impression that because (new A)->b is
disallowed in property initializers __get could never be triggered in
this context either but since the LHS of -> can be a constant
containing another object this is indeed possible. The problem is
described in the new in initializer RFC [1] you linked. There is
currently no appropriate place where evaluation of the expression
could happen without potential side-effects in places where we don't
want them, like unserialize.

Unfortunately, while thinking about this case I also discovered another issue.

class A {
    public $b = 'b';
}
const A = new A;

class C {
    public $b = A->b;
}

var_dump(new C());
$a = A;
$a->b = 'b2';
var_dump(new C());

Even without __get the property of an object referenced in the LHS of
the -> operator can change. The engine evaluates the default property
values once for the entire class and then copies the result whenever a
new instance of that class gets created. That means further instances
will use the out-dated property default value from when the first
instance was created. Similarly, function default parameters get
cached between calls. We could evaluate the constant expression for
each object instantiation or function call but degrading performance
for an edge case doesn't seem worth it.

Since the primary motivation of this RFC is to allow fetching the name
and value properties of enums I'm inclined to forbid using -> on
anything but enums. That would circumvent the issue since enums can't
contain user-defined properties nor the magic __get method, and
name/value are readonly.

I'll take a few days to think about the options, and will update the
RFC and inform the mailing list about the decision I have made. Let me
know if you have any more thoughts.

Ilija

[1] https://wiki.php.net/rfc/new_in_initializers#unsupported_positions

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to