Skip to content

Conversation

hikari-no-yume
Copy link
Contributor

Counterpart to RFC: https://wiki.php.net/rfc/void_return_type

Based on and essentially reviving this earlier pull request: #1084

@laruence laruence added the RFC label Oct 15, 2015
@naroga
Copy link

naroga commented Oct 15, 2015

Question: how will the compiler deal with:

function myFunc() : void { ... }
$myVar = myFunc();

Will it throw an error, or will it assign null to $myVar? There is a minor discussion going on at reddit, and I kind of agree that it makes sense to disallow a return assignment for void functions, since null is a perfectly valid return type and is explicitly disallowed for void functions.

I mean, it should be disallowed in compile-time, not in runtime.

@hikari-no-yume
Copy link
Contributor Author

It just assigns null, as we already do for built-in PHP functions documented as void.

We could change this, but it would break existing code, and it's inconvenient (can't safely pass along the return value of a callback, for instance).

@naroga
Copy link

naroga commented Oct 15, 2015

So, to caller POV, it makes no difference if the function is prohibited from returning a value? The only place the void return type affects is within the function itself?

Seems a little odd that I can forbid a return, and use the function return (which is inexistent and cannot even be null) as a value. It should at least throw an E_NOTICE.

"You can't return null, but null will still be returned" stikes me as an odd design choice.

I agree it's inconvenient, but that's the inconvenience strict typing brings. Most languages would complain about using a void function return as a value, wouldn't them?

@hikari-no-yume
Copy link
Contributor Author

Some do, some don't.

It doesn't really matter if the caller gets a value or not.

@naroga
Copy link

naroga commented Oct 15, 2015

It doesn't really matter if the caller gets a value or not.

I kind of agree, but the same applies to accessing a variable that wasn't initiated. It throws an E_NOTICE and gets NULL as its value. It didn't really matter if the variable was initiated or not, because it did get a NULL. I guess the same should apply to using the return value of a void function.

@vlakarados
Copy link

I see a point where void returning functions should be allowed in callbacks, but isn't this an edge case that should be treated as an exception? I think it's better to get compile time errors when using the return value of such a function, that would prevent users to get unexpected results, especially when updating libraries that returned some result, but will return void after updating. Anyway, this is something I desperately wish to see implemented.

@IceReaper
Copy link

What about this: We have declare(strict_types=1); - Why not use this to toggle it? While non-strict we might want to "return" null, or leave the variable undefined or unchanged. In strict mode, this should throw an exception.

@vlakarados
Copy link

@IceReaper though I partially agree it's somewhat related, it's counter intuitive and it adds additional, abnormal functionality to the concrete declaration

@jesseschalken
Copy link

@naroga null is PHP's unit type i.e. the type which contains exactly one value and therefore no information. Disallowing the use of the return value from a void function and allowing it but knowing it will be null is semantically equivalent: in either case you have no extra information.

However, considering all functions as returning a value which will simply be null in the case of void functions is simpler, matches what PHP already does and is also useful for callbacks and generics.

Consider this function:

function foo<T>(function ():T $bar):Baz<T> { /* ... */ }

If you already have a function returning void, you can pass it straight to foo() using null for T and it will have no problem since it is allowed to use the return value:

function bar(function ():void $boo) {
    $baz = foo<null>($boo);
    // ...
}

If the return value of a void function cannot be used then you are forced to wrap it in a closure returning null explicitly:

function bar(function ():void $boo) {
    $baz = foo<null>(function ():null use ($boo) { $boo(); return null; });
    // ...
}

In other words you will be forced to convert between functions returning null and functions returning void even though the distinction is meaningless.

@hikari-no-yume
Copy link
Contributor Author

The RFC has now been accepted: http://news.php.net/php.internals/89110

So, this should hopefully be merged sometime soon. Is there anything I've missed with the pull request at present?

@@ -975,6 +993,8 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
} else if (ret_info->type_hint == _IS_BOOL &&
EXPECTED(Z_TYPE_P(ret) == IS_FALSE || Z_TYPE_P(ret) == IS_TRUE)) {
/* pass */
} else if (ret_info->type_hint == IS_VOID) {
zend_verify_void_return_error(zf, zend_zval_type_name(ret), "");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since internal 'void' functions (the ones we mark in prototypes and the manual with void) actually have to explicitly return null, the internal return type checking path for them ought to permit returning null.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Come to think of it, why bother enforcing internal return types anyway?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just for debugging. We don't do internal function return type checks in release builds.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, gotcha.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait, I don't need to change anything. NULL will already be accepted if allow_null is set to 1.

Though that makes reflection info a bit weird.

@hikari-no-yume hikari-no-yume force-pushed the void_return_type_7.1 branch 2 times, most recently from c8532dd to 3c4f88d Compare November 9, 2015 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants