On 5.6.2025 02:59:56, Daniel Scherzer wrote:
On Wed, Jun 4, 2025 at 4:49 PM Bob Weinand <bobw...@hotmail.com> wrote:
Hey Daniel,
where's the BC break? Nothing which worked today will stop working
(except you won't get exceptions in some cases). That's not a BC
break. The only thing which stops working is if it's intentionally
used as a guard.
That (intentionally using `void` returns as a guard) is exactly what
MediaWiki does. MediaWiki has an interface for each hook, that
requires that hooks that cannot abort (return false) must return void;
https://www.mediawiki.org/wiki/Manual:Hooks#Handling_hooks_in_MediaWiki_1.35_and_later.
PHP is used to help enforce this.
However, in the case of MediaWiki they do actually _care_ about
the return type (and the caller of these hooks will actually check
for null/true/false). So it should be annotated ": null". And not
": void". Explicit intentions are important.
They probably still use ": void" as to be compatible with PHP 8.1
and older. ": null" is only supported starting PHP 8.2. I'd assume
as they upgrade their required PHP version (8.1 currently) they'll
shift to ": null".
So, yeah, the guard will lose its guarding functionality (but we
don't consider that a BC break).
Why is this not considered a BC break? You can consider it a small
break, but I think it should be noted in the BC section of the RFC.
It's a small break in the sense of workflow, but *compatibility* breaks
are concerned with the behaviours of non-erroneous functionality. (Code
with worked yesterday works today. And not code which did not work
yesterday works today).
But sure, the RFC may indicate it.
Regarding why not mixed? Because the intention with mixed is that
the value is something meaningful. With void it's meaningless.
There's a semantic distinction (and it forbids returning). And, as
proposed, you could forbid direct calls of void functions giving
runtime / static analysis hints. With void being covariant with
respect to child functions now.
Bob
If `void` is a top type indicating a return is meaningless, then
callers would have no reason to examine the returned value, and then
when subclasses do try to add meaning it might be missed. Am I missing
something? How would void be different from "the base implementation
happens to always return null, but subclasses can return other things,
and the result can be meaningful"?
-Daniel
What LSP builds upon is "if I code against this interface, my
expectations will always be fulfilled". If I code against the interface
returning void, I do not care about the actual returned value and such
my expectations are always fulfilled.
If I code against some subclass (or any of its children) which has a
meaningful return type specified, and I'm aware of that return type, I
may for sure use the return value. Nothing requires me to actually use
the return value. It's similar to optional parameters "When subclasses
do try to add optional parameters, they might be missed". That line of
argumentation is a bit absurd :-)
Bob