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

Reply via email to