Fix #79679: Constructor can not return any value (always void)#5678
Fix #79679: Constructor can not return any value (always void)#5678mvorisek wants to merge 3 commits intophp:masterfrom
Conversation
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: A void function must not return a value in %s:%d |
There was a problem hiding this comment.
Specific Constructor must not return a value message might be better
But see https://3v4l.org/dbVah. |
|
@cmb69 delete that 5 :D |
|
Oh, right, but in my opinion, declaring |
|
So either nothing or About the destructor, do you think it should be added to that related RFC/PR? |
I assume you're referring to https://wiki.php.net/rfc/magic-methods-signature. That RFC explicitly excludes changes to Anyhow, potential implementation to allow Zend/zend_compile.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 86e169893a..509a7fcda0 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -6894,7 +6894,8 @@ void zend_compile_class_decl(znode *result, zend_ast *ast, zend_bool toplevel) /
zend_error_noreturn(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static",
ZSTR_VAL(ce->name), ZSTR_VAL(ce->constructor->common.function_name));
}
- if (ce->constructor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
+ if (ce->constructor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE
+ && ZEND_TYPE_PURE_MASK(ce->constructor->common.arg_info[-1].type) != MAY_BE_VOID) {
zend_error_noreturn(E_COMPILE_ERROR,
"Constructor %s::%s() cannot declare a return type",
ZSTR_VAL(ce->name), ZSTR_VAL(ce->constructor->common.function_name));
@@ -6904,7 +6905,8 @@ void zend_compile_class_decl(znode *result, zend_ast *ast, zend_bool toplevel) /
if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
zend_error_noreturn(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static",
ZSTR_VAL(ce->name), ZSTR_VAL(ce->destructor->common.function_name));
- } else if (ce->destructor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
+ } else if (ce->destructor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE
+ && ZEND_TYPE_PURE_MASK(ce->destructor->common.arg_info[-1].type) != MAY_BE_VOID) {
zend_error_noreturn(E_COMPILE_ERROR,
"Destructor %s::%s() cannot declare a return type",
ZSTR_VAL(ce->name), ZSTR_VAL(ce->destructor->common.function_name));
|
|
@cmb69 feel free to commit it here directly, but constructor is very special, I am not sure if this will be not misused by other people by simply adding is everywhere (or is that desired?) Anyway, I think constructor as well as destructor should be not allowed to return anything because the return can not be used when used with "new" or when called by GC. capturing value from
Yes, but the RFC is saying something that is not fully true. So I think it makes sense to extend it after short internal discussion/approval. That is up to you guys :) |
Do you have an example in any other language where constructors and destructors return anything? |
My point is that |
I reacted on, citing:
so for these reasons I think it should be part of your RFC and I think the community will be ok with that |
That is true, but based on the proposed RFC for other special methods this will no longer be true, so this argumentation is no longer valid then - I think the only possible scenarion, when |
|
It really shouldn't be necessary (and by induction, allowed) to add |
|
@cmb69 Can you advice what to add to modify the parser to parse every constructor method like if it was defined inside |
|
I think you can do something like: Zend/zend_compile.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index a2c8b9f23e..e64c3e0527 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -6464,8 +6464,15 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /*
zend_stack_push(&CG(loop_var_stack), (void *) &dummy_var);
}
- zend_compile_params(params_ast, return_type_ast,
- is_method && zend_string_equals_literal_ci(decl->name, "__toString") ? IS_STRING : 0);
+ uint32_t fallback_return_type = 0;
+ if (is_method) {
+ if (zend_string_equals_literal_ci(decl->name, "__toString")) {
+ fallback_return_type = IS_STRING;
+ } else if (zend_string_equals_literal_ci(decl->name, "__construct")) {
+ fallback_return_type = IS_VOID;
+ }
+ }
+ zend_compile_params(params_ast, return_type_ast, fallback_return_type);
if (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) {
zend_mark_function_as_generator();
zend_emit_op(NULL, ZEND_GENERATOR_CREATE, NULL, NULL); |
|
You need to also allow the |
|
The AppVeyor CI failure indicates that several test cases would need to be updated for this change. I'm not sure about the Travis CI failure; does this PR break pear? Anyhow, there is now https://wiki.php.net/rfc/constructor_return_type. |
@cmb69 I am happy if someone can take this idea to happen. I commented on the related PR and I am closing this PR for now. |
|
Since you were the original author of this PR, I will happily add credits to you in the RFC 😄. I personally wanted to only make an RFC for allowing Best regards, |
Thanks - please add me there as "Michael Voříšek <vorismi3 (at) fel.cvut.cz>". I already send you some feedback to your email. I pointed out there that currently constructor method can return non-void but when the object is instanced the value can not be read. So for these reasons, I think we should at least offer one paragraph to that in that RFC and vote about it extra. The same for destructor, what is the possitive of allowing to return something from destructor method? I propose to imply implicit void by default for these methods and throw on compile time (like when void would be declared in the method header) |
|
Thanks, your email was marked as spam for me. Anyways, let's continue our discussion through email, I'll hit you up soon. |
test for https://bugs.php.net/bug.php?id=79679
current situation with
__construct()is:it seems like a bug to me
Please help with impl.
As it introduces a small BC break probably for PHP8 only.
__destructcan be declared with void (thus not clear bug like this) so it should be probably solved in this PR/RFC #4177