Immutable classes with pure constructor and same constant args as single object
In case of
$a = new A(CONST_ONE, CONST_TWO);
$b = new A(CONST_ONE, CONST_TWO);
we want
- Constructor of class
Awith parametersCONST_ONE, CONST_TWOto be called once and transpiled as global variable that is initialized only once - Each invocation of
new A(CONST_ONE, CONST_TWO)to be replaced with such a variable
It would allow use some constructions such as
const c = new A(CONST_ONE, CONST_TWO);
with the following restrictions on class A:
- Marked as
@kphp-immutable-class - Has constructor that marked as
@kphp-pure-function -
CONST_ONE, CONST_TWOare constant expressions
It would possibly improve performance and definitely help to implement enums in a natural way.
I strongly disagree about this change. Two independent calls of the constructor MUST return two independent instances, but suggested feature just breaks this rule and affects runtime.
In fact, this issue introduces some kind of compile-time singleton, but in a very implicit way (counterintuitive, in fact). Two identical objects, even immutable ones, are still not the same object in general case, so singletonization must be done in user code explicitly.
So this in not an optimization, but a breaking change.
I strongly disagree about this change. Two independent calls of the constructor MUST return two independent instances, but suggested feature just breaks this rule and affects runtime.
In fact, this issue introduces some kind of compile-time singleton, but in a very implicit way (counterintuitive, in fact). Two identical objects, even immutable ones, are still not the same object in general case, so singletonization must be done in user code explicitly.
So this in not an optimization, but a breaking change.
Thank you for the comment. Naturally, it's internal compiler change and it should not affect on current code bases because all constructors are not @kphp-pure-function-ed. According to the idea, it doesn't matter for kphp-user how such classes are transpiled.
Could you give an example of breaking cases, please?
Could you give an example of breaking cases, please?
I missed the fact that @kphp-pure-function is currently supported only for built-in functions, so you're right, current behaviour won't change. Is the issue about implementing the annotation for constructors (and other user-code functions) as well?
By the way, such behaviour can't be achieved in pure PHP, so there will be inconsistency between PHP and KPHP.
Is the issue about implementing the annotation for constructors (and other user-code functions) as well?
Not really. Actually, this annotation is implemented, but behavior is not guaranteed. There's going to be another issue about dealing with @kphp-pure-function.
For now, the most motivated example is enum implementation.
Do you mean it's gonna be kind of workaround while there's no real enum, like for PHP <= 8.1? Or this blocks #730 in some way?
Do you mean it's gonna be kind of workaround while there's no real
enum, like for PHP <= 8.1? Or this blocks #730 in some way?
We decided to change a little bit initial idea. For now, we implemented a part of https://www.php.net/releases/8.1/en.php#new_in_initializers, namely it's possible to use objects in constant definition. See https://github.com/VKCOM/kphp/pull/814. Besides, we decided to (later) introduce new phpdoc for classes that forces to store every instance of this class which are constructed with same constant parameters in the same constant object.